hdu3367最大伪森林(并查集)
题目链接:http://icpc.njust.edu.cn/Problem/Hdu/3367/
题目要求一个连通图的最大伪森林,伪森林是一个最多有一个回路的图。我们只要用Kruskal最大生成树的策略就可以,给根节点表上记号表明这棵树有没有负环。其实也有一些贪心的思想。
代码如下:
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef unsigned int ui; 4 typedef long long ll; 5 typedef unsigned long long ull; 6 #define pf printf 7 #define mem(a,b) memset(a,b,sizeof(a)) 8 #define prime1 1e9+7 9 #define prime2 1e9+9 10 #define pi 3.14159265 11 #define lson l,mid,rt<<1 12 #define rson mid+1,r,rt<<1|1 13 #define scand(x) scanf("%llf",&x) 14 #define f(i,a,b) for(int i=a;i<=b;i++) 15 #define scan(a) scanf("%d",&a) 16 #define mp(a,b) make_pair((a),(b)) 17 #define P pair<int,int> 18 #define dbg(args) cout<<#args<<":"<<args<<endl; 19 #define inf 0x3f3f3f3f 20 const int maxn=1e6+10; 21 int n,m,t; 22 inline int read(){ 23 int ans=0,w=1; 24 char ch=getchar(); 25 while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();} 26 while(isdigit(ch))ans=(ans<<3)+(ans<<1)+ch-'0',ch=getchar(); 27 return ans*w; 28 } 29 int f[maxn]; 30 bool mark[maxn]; 31 struct node{ 32 int u,v,w; 33 }e[maxn]; 34 int ans; 35 void init() 36 { 37 f(i,0,n-1)f[i]=i; 38 mem(mark,0); 39 ans=0; 40 } 41 bool cmp(node& a,node& b) 42 { 43 return a.w>b.w; 44 } 45 int find(int x) 46 { 47 if(x==f[x])return x; 48 return f[x]=find(f[x]); 49 } 50 void Union(int x,int y,int w) 51 { 52 int fx=find(x); 53 int fy=find(y); 54 if(fx==fy) 55 { 56 if(!mark[fx]) 57 { 58 mark[fx]=1; 59 ans+=w; 60 } 61 } 62 else 63 { 64 if(!mark[fx]||!mark[fy]) 65 { 66 f[fx]=fy; 67 mark[fy]=mark[fx]||mark[fy];//两者都为零的时候fy不做标记,但是两者中有一个是零的时候就会做标记 68 ans+=w; 69 } 70 } 71 } 72 int main() 73 { 74 //freopen("input.txt","r",stdin); 75 //freopen("output.txt","w",stdout); 76 std::ios::sync_with_stdio(false); 77 while(1) 78 { 79 n=read(),m=read(); 80 init(); 81 if(n==0&&m==0)break; 82 f(i,1,m) 83 { 84 scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w); 85 } 86 sort(e+1,e+m+1,cmp); 87 f(i,1,m) 88 { 89 Union(e[i].u,e[i].v,e[i].w); 90 } 91 pf("%d\n",ans); 92 } 93 }
每一个不曾起舞的日子,都是对生命的辜负。