Description
Input
Output
Sample Input
4 4 1 2 3 1 3 3 2 3 3 2 4 3
Sample Output
1 3题意:这题就是求哪一条边是必须要用的才能构成最小生成树,之后再将其数值全部加起来就是答案了。思路:首先要找出最小生成树的总和是多少,然后是将构成那颗树的所有边都存起来,之后再删除一条边,看能否又找到总和相同的树,如果能就说明我可以用另外的边去代替被删除的边,即不是不可替代的边。AC代码:#include<iostream> #include<algorithm> #include<cstring> #include<cstdio> #include<vector> typedef unsigned long long ll; using namespace std; #define T 1500000 int n,m,c; int par[T]; int nu[T]; struct node { int u,v,w; bool operator<(const node& a)const{ return w<a.w; } }e[T]; int find(int x) { int s = x; for(;s!=par[s];s=par[s]); while(s!=x) { int tmp = par[x]; par[x] = s; x = tmp; } return s; } int kruskal(int x) { for(int i=0;i<=n;++i){ par[i] = i; } int num = 0, cost = 0; for(int i=0;i<m;++i){ if(x==i)continue; int tx = find(e[i].u),ty = find(e[i].v); if(tx!=ty){ par[tx] = ty; cost += e[i].w; num++; if(x==-1)nu[c++] = i; } if(num==n-1)break; } return cost; } int main() { #ifdef zsc freopen("input.txt","r",stdin); #endif int i; while(~scanf("%d%d",&n,&m)) { c = 0; for(i=0;i<m;++i){ scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w); } sort(e,e+m); int w1 = kruskal(-1),w2,cost=0,cnt=0; for(i=0;i<c;++i){ w2 = kruskal(nu[i]); if(w2!=w1){ cost += e[nu[i]].w;cnt++; } } printf("%d %d\n",cnt,cost); } return 0; }