HDU 2121 Ice_cream’s world II
无固定根的最小树形图。。。
虚拟一个节点(0号节点),其到其余N个点的边权都为所有M条边的权值和(sum)+1,然后以此为Root跑朱刘算法,最后判断连接到0号节点的节点数目是不是1,若是1输出
输出ans - sum - 1,否则无解。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 #include<vector> 6 #include<stack> 7 #include<queue> 8 #include<map> 9 #include<cstdlib> 10 #include<cmath> 11 using namespace std; 12 #define ll long long 13 #define pb push_back 14 const int MAXM = 10005; 15 const int MAXN = 1005; 16 int node,n,m,x,y,z,nume,cnt,root,broot,et; 17 int g[MAXN]; 18 int pre[MAXN]; 19 ll mc[MAXN]; 20 long long sum; 21 int s[MAXN]; 22 struct edge 23 { 24 int u,v,nxt,bu,bv; 25 ll c; 26 }; 27 edge e[MAXM]; 28 void init() 29 { 30 nume = 1; 31 memset(g,0,sizeof(g)); 32 } 33 void addedge(int u,int v,ll c,int judge) 34 { 35 if (u == v) return; 36 if (judge) sum+=c; 37 ++nume; 38 e[nume].u = e[nume].bu = u; 39 e[nume].v = e[nume].bv = v; 40 e[nume].c = c; 41 e[nume].nxt = g[u]; 42 g[u] = nume; 43 } 44 void find_mincost() 45 { 46 memset(pre,0,sizeof(pre)); 47 memset(mc,63,sizeof(mc)); 48 for (int i = 1; i <= nume; i++) 49 if (e[i].v != e[i].u) 50 { 51 if (mc[e[i].v] > e[i].c && e[i].v != root) 52 { 53 mc[e[i].v] = e[i].c; 54 pre[e[i].v] = i; 55 } 56 } 57 } 58 bool dfs(int x,int y) 59 { 60 int z = e[pre[x]].u; 61 if (z == 0) return 0; 62 if (s[z] == 0) 63 { 64 s[z] = cnt; 65 if (!dfs(z,y)) s[z] = 0; 66 else return 1; 67 } 68 else return z == y; 69 return 0; 70 } 71 int main() 72 { 73 while (scanf("%d%d",&n,&m) != EOF) 74 { 75 init(); 76 sum = 0; 77 for (int i = 1; i <= m; i++) 78 { 79 scanf("%d%d%d",&x,&y,&z); 80 x++; y++; 81 addedge(x,y,z,1); 82 } 83 sum++; 84 //cout<<sum<<endl; 85 for (int i = 1; i <= n; i++) addedge(n + 1,i,sum,0); 86 // cout<<sum<<endl; 87 n++; 88 root = n; cnt = n; broot = n; node = 0; 89 long long ans = 0; 90 //et = 0; 91 while (1) 92 { 93 et = 0; 94 find_mincost();//cout<<sum<<endl; 95 //for (int i = 1; i <= n; i++) cout<<i<<" "<<mc[i]<<" "<<pre[i]<<endl; 96 for (int i = 1; i <= n; i++) 97 if (i != root) ans += mc[i]; 98 for (int i = 1; i <= n; i++) 99 { 100 if (pre[i] == 0) continue; 101 int x = pre[i]; 102 // cout<<i<<" "<<e[x].bu<<endl; 103 if (e[x].bu == broot) 104 { 105 et++; 106 node = e[x].bv; 107 //cout<<et<<" "<<node<<"O"<<endl; 108 } 109 } 110 memset(s,0,sizeof(s)); 111 cnt = 0; 112 int cir = 0; 113 for (int i = 1; i <= n; i++) 114 if (!s[i]) 115 { 116 cnt++; 117 s[i] = cnt; 118 if (dfs(i,i)) 119 { 120 cir++; 121 } 122 } 123 //cout<<root<<" "<<cnt<<" "<<cir<<endl; 124 //cout<<m<<endl; 125 if (cir == 0) break; 126 for (int i = 1; i <= nume; i++) 127 { 128 int x = e[i].u,y = e[i].v; 129 e[i].u = s[x]; e[i].v = s[y]; 130 if ((e[i].u != e[i].v)) 131 { 132 //cout<<1<<endl; 133 e[i].c -= mc[y]; 134 } 135 } 136 //for (int i = 1; i <= m; i++) cout<<e[i].u<<" "<<e[i].v<<" "<<e[i].c<<endl; 137 n = cnt; 138 root = s[root]; 139 } 140 //cout<<et<<endl; 141 //cout<<ans<<" "<<sum<<endl; 142 if (et == 1) printf("%I64d %d\n",ans - sum,node - 1); 143 else puts("impossible"); 144 printf("\n"); 145 } 146 return 0; 147 }