POJ3723-Conscription
链接:http://poj.org/problem?id=3723
显然求最小生成树。但该图不一定是连通图,所以每处理一棵树还要找下一棵。为了方便,不妨让女孩的标号为0到n-1,而男孩的标号为n到m-1,这样便可放在统一数组记录。
代码(prim算法):
1 #include <iostream> 2 #include <cstdio> 3 #include <vector> 4 #include <queue> 5 #include <algorithm> 6 using namespace std; 7 const int INF=10000; 8 typedef pair<int,int> P; 9 int n,m,r,t,f[21000],d[21000]; 10 struct edge 11 { 12 int to,cost; 13 edge(int to,int cost):to(to),cost(cost){} 14 }; 15 vector<edge>G[21000]; 16 void prim(void) 17 { 18 int ans=0; 19 for(int i=0;i<n+m;i++) 20 { 21 if(!f[i]) 22 { 23 priority_queue<P,vector<P>,greater<P> > que; 24 que.push(P(10000,i)); 25 while(!que.empty()) 26 { 27 P p=que.top();que.pop(); 28 int v=p.second; 29 if(d[v]<p.first)continue; 30 if(!f[v])ans+=d[v]; 31 f[v]=1; 32 for(int j=0;j<G[v].size();j++) 33 { 34 edge e=G[v][j]; 35 if(d[e.to]>e.cost&&e.to!=i) 36 { 37 d[e.to]=e.cost; 38 que.push(P(d[e.to],e.to)); 39 } 40 } 41 } 42 } 43 } 44 printf("%d\n",ans); 45 } 46 int main(void) 47 { 48 scanf("%d",&t); 49 while(t--) 50 { 51 scanf("%d %d %d",&n,&m,&r); 52 for(int i=0;i<n+m;i++) 53 { 54 d[i]=INF; 55 f[i]=0; 56 G[i].clear(); 57 } 58 for(int i=1;i<=r;i++) 59 { 60 int u,v,d; 61 scanf("%d %d %d",&u,&v,&d); 62 G[u].push_back(edge(v+n,10000-d)); 63 G[v+n].push_back(edge(u,10000-d)); 64 } 65 prim(); 66 } 67 }
终究独木难支。