来源:UVA11183
朱刘算法求最小树形图
代码:
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int INF = 0x3f3f3f3f;
const int MAXE = 40000+10;
const int MAXV = 1010;
struct Edge{
int u,v;
int cost;
}edge[MAXE];
int n,m;
int mp[MAXV][MAXV];
int pre[MAXV],id[MAXV],vis[MAXV],in[MAXV];
int zhuliu(int root,int n,int m){
int ans = 0;
int u,v;
while(1){//朱刘算法要求一直做到没有有向环
for(int i=0;i<n;i++){
in[i] = INF;
}
for(int i=0;i<m;i++){
if(edge[i].u!=edge[i].v&&edge[i].cost<in[edge[i].v])
{
// cout<<"in"<<endl;
pre[edge[i].v] = edge[i].u;
in[edge[i].v] = edge[i].cost;
}
}
for(int i=0;i<n;i++)
if(i!=root&&in[i]==INF)
return -1;//判联通
int tn=0;
memset(id,-1,sizeof(id));
memset(vis,-1,sizeof(vis));
in[root] = 0;
for(int i=0;i<n;i++){
ans+=in[i];
v=i;
while(vis[v]!=i&&id[v]==-1&&v!=root){
vis[v]=i;
v=pre[v];
}
if(v!=root&&id[v]==-1){
for(int u =pre[v];u!=v;u=pre[u]){
id[u] = tn;
}
id[v]=tn++;
}
}
if(tn==0) break;
for(int i=0;i<n;i++){
if(id[i]==-1){
id[i]=tn++;
}
}
for(int i=0;i<m;){
v = edge[i].v;
edge[i].u = id[edge[i].u];
edge[i].v = id[edge[i].v];
if(edge[i].u!=edge[i].v){
edge[i++].cost-=in[v];
}
else{
swap(edge[i],edge[--m]);
}
}
n=tn;
root = id[root];
}
return ans;
}
int main(){
int T,nc=1;
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&m);
//cout<<n<<" "<<m<<endl;
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
mp[i][j]=INF;
}
}
int u,v,w;
for(int i=0;i<m;i++){
scanf("%d%d%d",&u,&v,&w);
if(u==v) continue;
mp[u][v] = min(mp[u][v],w);
}
int cnt = 0;
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(mp[i][j]<INF){
// cout<<"xianin ";
edge[cnt].u=i;
edge[cnt].v=j;
edge[cnt++].cost=mp[i][j];
// cout<<i<<" "<<j<<" "<<mp[i][j]<<endl;
}
}
}
int ans = zhuliu(0,n,cnt);
cout<<"Case #"<<nc++<<": ";
if(ans==-1) cout<<"Possums!"<<endl;
else cout<<ans<<endl;
}
return 0;
}