CSU 1541There is No Alternative (最小生成树判相同边)
1541: There is No Alternative
Time Limit: 3 Sec Memory Limit: 256 MBSubmit: 98 Solved: 31
[Submit][Status][Web Board]
Description
Input
Output
Sample Input
4 4
1 2 3
1 3 3
2 3 3
2 4 3
Sample Output
1 3
HINT
Source
题目的意思就是建造桥,问在建造桥的最小花费的方案中,有哪些桥是必须要建的
把桥连接起来然后求最小造价是最小生成树,这里的话,判定有哪些边是一定要建造的,就先生成最小生成树,然后枚举去掉每一条边,如果得出来的最小生成树的值和第一次的相同,那么该边可以被替代,如果生成的值不一样的话,那么该边就不能被替代
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<ctype.h> #include<queue> #include<stack> #include<stdlib.h> #include<algorithm> using namespace std; const int MAXN=1000000+5; int n,m,cnt,result,num; struct node { int x,y,val; bool operator<(const node A)const { return val<A.val; } }a[MAXN]; int p[500+5],b[MAXN],vis[MAXN]; int finfa(int x) { return p[x]==x?x:p[x]=finfa(p[x]); } void init() { for(int i=1;i<=n;i++) p[i]=i; } int kru(int flag) { int res=0; for(int i=1;i<=m;i++) { if(vis[i]==1) continue; int x=finfa(a[i].x); int y=finfa(a[i].y); if(x!=y) { p[x]=y; res+=a[i].val; if(flag==0) b[cnt++]=i;//分别用flag=0/1判断是不是第一次生成最小生成树,第一次要把每一条边记录下来 } } return res; } int main() { scanf("%d %d",&n,&m); for(int i=1;i<=m;i++) scanf("%d %d %d",&a[i].x,&a[i].y,&a[i].val); sort(a+1,a+m+1); init(); cnt=0; num=0; result=0; int ans=kru(0); for(int i=0;i<cnt;i++) { init(); vis[b[i]]=1; if(kru(1)!=ans) { result+=a[b[i]].val; num++; } vis[b[i]]=0; } printf("%d %d\n",num,result); return 0; }