最小树形图模板 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 }