LightOj 1123-Trail Maintenance(最小生成树:神级删边)

1123 - Trail Maintenance

Time Limit: 2 second(s) Memory Limit: 32 MB

Tigers in the Sunderbans wish to travel freely among the N fields (numbered from 1 to N), even though they are separated by trees. The tigers wish to maintain trails between pairs of fields so that they can travel from any field to any other field using the maintained trails. Tigers may travel along a maintained trail in either direction.

The tigers do not build trails. Instead, they maintain deer trails that they have discovered. On any week, they can choose to maintain any or all of the deer animal trails they know about. Always curious, the tigers discover one new deer trail at the beginning of each week. They must then decide the set of trails to maintain for that week so that they can travel from any field to any other field. Tigers can only use trails which they are currently maintaining.

The tigers always want to minimize the total length of trail they must maintain. The tigers can choose to maintain any subset of the deer trails they know about, regardless of which trails were maintained the previous week. Deer trails (even when maintained) are never straight. Two trails that connect the same two fields might have different lengths. While two trails might cross, tigers are so focused; they refuse to switch trails except when they are in a field. At the beginning of each week, the tigers will describe the deer trail they discovered. Your program must then output the minimum total length of trail the tigers must maintain that week so that they can travel from any field to any other field, if there is such a set of trails.

Input

Input starts with an integer T (≤ 25), denoting the number of test cases.

Each case starts with two integers N (1 ≤ N ≤ 200) and WW is the number of weeks the program will cover (1 ≤ W ≤ 6000).

Each of the next W lines will contain three integers describing the trail the tigers found that week. The first two numbers denote the end points (filed numbers) and the third number denotes the length of the trail (1 to 10000). No trail has the same field as both of its end points.

Output

For each case, print the case number in a line. Then for every week, output a single line with the minimum total length of trail the tigers must maintain so that they can travel from any field to any other field. If no set of trails allows the tigers to travel from any field to any other field, output "-1".

Sample Input

Output for Sample Input

1

4 6

1 2 10

1 3 8

3 2 3

1 4 3

1 3 6

2 1 2

Case 1:

-1

-1

-1

14

12

8



题意:给n个点,m条边。对于每输入一条边。求此时(包含前面输入的边)的最小生成树,好吧,我承认这题实在是太猛了。一開始我直接套Krustra。直接TLE,后来參考某大牛。原来我直接上的O(n*m)的复杂度,后来一想是这种。对于每输入一条边,以此时的边的总数作为总数来求生成树,而且,在合并的过程中要有一个删边的优化,即假设遇到一条和之前选到MST中的边之中的一个 在同一个集合里(即有环) 那么要删除这条边,(非常好理解由于之前已经挑选到了最合适的边了,所以这条边就不须要了。即2选1 仅仅能选最优,否则就会形成环) 
#include <cstdio>
#include <iostream>
#include <cstring>
#include <cctype>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <list>
using namespace std;
const  int maxn=5000;
const int INF=1<<25;
int n,m,u[maxn],v[maxn],w[maxn],eg[maxn],fa[maxn];
void Make_set()
{
	for(int i=0;i<=n;i++)
		fa[i]=i;
}
int Find(int x)
{
	if(x==fa[x]) return x;
	return fa[x]=Find(fa[x]);
}
bool cmp(int a,int b)
{
	return w[a]<w[b];
}
int num;
int Kru()
{
	int d=-1,i,ans=0,cnt=0;
	Make_set();
	for(i=0;i<num;i++)
		eg[i]=i;
	sort(eg,eg+num,cmp);
	for(i=0;i<num;i++)
	{
		int e=eg[i];
		int fx=Find(u[e]);
		int fy=Find(v[e]);
		if(fx==fy)
		{
			d=e;
			continue;
		}
			fa[fx]=fy;
			ans+=w[e];
			cnt++;
	}
	if(d!=-1)//删边
	{
		num--;
		u[d]=u[num];
		v[d]=v[num];
		w[d]=w[num];
	}
	if(cnt==n-1)
	return ans;
	else
	return -1;
}
int main()
{
	int T,cas=1;
	scanf("%d",&T);
    while(T--)
	{
		scanf("%d%d",&n,&m);
		printf("Case %d:
",cas++);
		num=0;//边数
		for(int i=0;i<m;i++)
		{
			scanf("%d%d%d",&u[num],&v[num],&w[num]);
			num++;
			printf("%d
",Kru());
		}
	}
	return 0;
}
用结构体写了一下。还有要注意就是这题特别卡cin cout 
#include <cstdio>
#include <iostream>
#include <cstring>
#include <cctype>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <list>
using namespace std;
const  int maxn=500001;
const int INF=1<<29;
struct node{
	int u,v,w;
	friend bool operator<(node a,node b){
	return a.w<b.w;
	}
};
node eg[maxn];
int n,m,fa[maxn];
void Make_set()
{
	for(int i=1;i<=n;i++)
		fa[i]=i;
}
int Find(int x)
{
	if(x!=fa[x])
		fa[x]=Find(fa[x]);
	return fa[x];
}
int num;
int Kru()
{
	Make_set();
	sort(eg,eg+num);
	int ans=0,cnt=0,d=-1;
	for(int i=0;i<num;i++)
	{
		int fx=Find(eg[i].u);
		int fy=Find(eg[i].v);
		if(fx==fy)
		{
			d=i;
			continue;
		}
		else
		{
			fa[fx]=fy;
			ans+=eg[i].w;
			cnt++;
		}
	}
	    if(d!=-1) eg[d]=eg[--num];
		if(cnt==n-1) return ans;
	    return -1;
}
int main()
{
	int T,cas=1;
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d%d",&n,&m);
		printf("Case %d:
",cas++);
		num=0;
		for(int i=0;i<m;i++)
		{
			scanf("%d%d%d",&eg[num].u,&eg[num].v,&eg[num].w);
			num++;
			printf("%d
",Kru());
		}
	}
	return 0;
}



原文地址:https://www.cnblogs.com/yjbjingcha/p/6779939.html