最小树形图模板 UVA11183

题意:给定n个节点m条边的有向带权图,求以0为根节点的最小树形图权值大小

用这个代码的时候要注意,这里的数据是从0开始的,边也是从0开始算,

所以在打主代码的时候,如果是从1开始,那么算法里面的从0开始的位置也要相应修改。

特别是下面的  node_circle;   

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<string.h>
 4 using namespace std;
 5 const int maxn=1e3+10;
 6 const int maxm=4e4+10;
 7 const int inf=0x3f3f3f3f;
 8 int n,m;
 9 int cost[maxn],pre[maxn],vis[maxn],id[maxn];
10 struct node
11 {
12     int u,v,w;
13 }a[maxm];
14 int zhu_liu(int root)
15 {
16     int ans=0;
17     while(1){
18         for(int i=0;i<n;i++) cost[i]=inf;
19 
20         for(int i=0;i<m;i++){
21             int u=a[i].u,v=a[i].v,w=a[i].w;
22             if(cost[v]>w&&u!=v){
23                 pre[v]=u;
24                 cost[v]=w;
25             }
26         }
27 
28         for(int i=0;i<n;i++){
29             if(i==root) continue;
30             if(cost[i]==inf) return -1;
31         }
32 
33         int cnt_circle=0;
34         memset(id,-1,sizeof(id));
35         memset(vis,-1,sizeof(vis));
36         cost[root]=0;
37         for(int i=0;i<n;i++){
38             ans+=cost[i];
39             int p=i;
40             while(vis[p]!=i&&id[p]==-1&&p!=root)
41                 vis[p]=i,p=pre[p];
42             if(id[p]==-1&&p!=root){
43                 for(int u=pre[p];u!=p;u=pre[u]){
44                     id[u]=cnt_circle;
45                 }
46                 id[p]=cnt_circle++;
47             }
48         }
49         if(!cnt_circle) break;
50         for(int i=0;i<n;i++)
51             if(id[i]==-1) id[i]=cnt_circle++;
52         for(int i=0;i<m;i++){
53             int v=a[i].v;
54             a[i].u=id[a[i].u];
55             a[i].v=id[a[i].v];
56             if(a[i].u!=a[i].v){
57                 a[i].w=a[i].w-cost[v];
58             }
59         }
60         n=cnt_circle;
61         root=id[root];
62     }
63     return ans;
64 }
65 int main()
66 {
67     int T;
68     int cnt=0;
69     scanf("%d",&T);
70     while(T--){
71         scanf("%d%d",&n,&m);
72         for(int i=0;i<m;i++)
73             scanf("%d%d%d",&a[i].u,&a[i].v,&a[i].w);
74         int ans=zhu_liu(0);
75         printf("Case #%d: ",++cnt);
76         if(ans==-1) printf("Possums!\n");
77         else printf("%d\n",ans);
78     }
79     return 0;
80 }

 给出从1开始的代码;

这道题是以r为根,点是从1~n,

 1 #include<cstdio>
 2 #include<string.h>
 3 #include<algorithm>
 4 #include<queue>
 5 using namespace std;
 6 typedef long long ll;
 7 const int maxn=1e4+10;
 8 const ll inf=0x3f3f3f3f3f3f3f;
 9 struct node
10 {
11     ll u,v,w;
12 }a[maxn];
13 ll n,m;  //点的个数和边的个数都要定在全局变量,因为zhuliu里用到;
14 ll cost[maxn],pre[maxn],vis[maxn],id[maxn];
15 ll zhu_liu(ll root)
16 {
17     ll ans=0;
18     while(1){
19         for(ll i=1;i<=n;i++) cost[i]=inf;
20 
21         for(ll i=1;i<=m;i++){
22             ll u=a[i].u,v=a[i].v,w=a[i].w;
23             if(cost[v]>w&&u!=v){
24                 pre[v]=u;
25                 cost[v]=w;
26             }
27         }
28 
29         for(ll i=1;i<=n;i++){
30             if(i==root) continue;
31             if(cost[i]==inf) return -1; //无法构成就输出-1;
32         }
33 
34         ll cnt_circle=1;
35         memset(id,-1,sizeof(id));
36         memset(vis,-1,sizeof(vis));
37         cost[root]=0;
38         for(ll i=1;i<=n;i++){
39             ans+=cost[i];
40             ll p=i;
41             while(vis[p]!=i&&id[p]==-1&&p!=root)
42                 vis[p]=i,p=pre[p];
43             if(id[p]==-1&&p!=root){
44                 for(ll u=pre[p];u!=p;u=pre[u]){
45                     id[u]=cnt_circle;
46                 }
47                 id[p]=cnt_circle++;
48             }
49         }
50         if(cnt_circle==1) break;
51         for(ll i=1;i<=n;i++)
52             if(id[i]==-1) id[i]=cnt_circle++;
53         for(ll i=1;i<=m;i++){
54             ll v=a[i].v;
55             a[i].u=id[a[i].u];
56             a[i].v=id[a[i].v];
57             if(a[i].u!=a[i].v){
58                 a[i].w=a[i].w-cost[v];
59             }
60         }
61         n=cnt_circle-1;
62         root=id[root];
63     }
64     return ans;
65 }
66 int main()
67 {
68     ll r;
69     while(scanf("%lld%lld%lld",&n,&m,&r)!=EOF){
70         for(ll i=1;i<=m;i++){
71             scanf("%lld%lld%lld",&a[i].u,&a[i].v,&a[i].w);
72         }
73         ll ans=zhu_liu(r);
74         printf("%lld\n",ans);
75     }
76     return 0;
77 }

 

posted @ 2019-09-24 12:31  古比  阅读(171)  评论(0编辑  收藏  举报