最小树形图朱刘算法
大概流程:
初始化答案ans=0
1.每个点
v
v
选个最小入边,如果有点没有
prec
p
r
e
c
就无解
2.
∑i,i≠rootans+=prec[i]
∑
i
,
i
≠
r
o
o
t
a
n
s
+
=
p
r
e
c
[
i
]
2.若最小入边构成的是一棵树,那这个就是答案
3.否则最小入边会构成一棵树和若干个环,建一个新图
G′
G
′
,在新图中把环缩成一个点
v′
v
′
4.设点
x
x
在新图中对应点,对于原图中的一条边
(u,v,w)
(
u
,
v
,
w
)
,若他在新图中不是一个自环,建边
(u′,v′,w−prec[v])
(
u
′
,
v
′
,
w
−
p
r
e
c
[
v
]
)
,然后回到步骤1
板子
hdu2121
code:
#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
#define pb push_back
#define SZ(x) (int)x.size()
#define mp make_pair
#define fir first
#define sec second
using namespace std;
const int maxn = 11000;
const int maxm = 11000;
ll ans,sum; int root;
int n,m;
struct node
{
int ty,y; ll c;
node(){}
node(int _ty,int _y,ll _c){ty=_ty,y=_y,c=_c;}
};
vector<node>G[maxn],nG[maxn];
ll pc[maxn];
int pi[maxn],pv[maxn];
void init()
{
ans=0,sum=0;
for(int i=1;i<=n+1;i++) G[i].clear(),nG[i].clear(),pc[i]=LLONG_MAX,pv[i]=0,pi[i]=0;
}
int id[maxn],cnt;
int vis[maxn];
int solve(int rt)
{
while(1)
{
for(int i=1;i<=n;i++) if(i!=rt&&!pv[i]) return 0;
for(int i=1;i<=n;i++) ans+=pc[i];
int cir=0; cnt=0;
for(int i=1;i<=n;i++) vis[i]=0,id[i]=0;
vis[rt]=-1;
for(int i=1;i<=n;i++)
{
int u;
for(u=i;!vis[u];u=pv[u]) vis[u]=i;
if(vis[u]==i)
{
cir=1;
id[u]=++cnt;
for(int v=pv[u];v!=u;v=pv[v]) id[v]=cnt;
}
}
for(int i=1;i<=n;i++) if(!id[i]) id[i]=++cnt;
if(!cir)
{
for(int i=1;i<=n;i++) if(i!=rt&&pv[i]==rt) root=pi[i];
return ans<2*sum;
}
for(int i=1;i<=cnt;i++) nG[i].clear();
for(int i=1;i<=n;i++)
{
for(int j=0;j<SZ(G[i]);j++)
{
int y=G[i][j].y; ll c=G[i][j].c-pc[y];
if(id[i]==id[y]) continue;
nG[id[i]].pb(node(G[i][j].ty,id[y],c));
}
}
n=cnt;
for(int i=1;i<=n;i++) pc[i]=LLONG_MAX,pi[i]=pv[i]=0;
for(int i=1;i<=n;i++)
{
G[i].clear();
for(int j=0;j<SZ(nG[i]);j++)
{
G[i].pb(nG[i][j]);
int y=G[i][j].y; ll c=G[i][j].c;
if(c<pc[y]||(c==pc[y]&&G[i][j].ty<pi[y]))
pc[y]=c,pv[y]=i,pi[y]=G[i][j].ty;
}
}
pc[rt=id[rt]]=0;
}
}
int main()
{
//freopen("tmp.in","r",stdin);
//freopen("tmp.out","w",stdout);
while(scanf("%d%d",&n,&m)!=EOF)
{
init();
for(int i=1;i<=m;i++)
{
int x,y;ll c; scanf("%d%d%lld",&x,&y,&c);
x++,y++;
if(x==y) continue;
G[x].pb(node(y,y,c));
sum+=c;
if(pc[y]>c) pc[y]=c,pv[y]=x,pi[y]=y;
}
sum++;
for(int i=1;i<=n;i++)
{
G[n+1].pb(node(i,i,sum));
if(pc[i]>sum) pc[i]=sum,pv[i]=n+1,pi[i]=i;
}
pc[++n]=0;
if(!solve(n)) puts("impossible");
else printf("%lld %d\n",ans-sum,root-1);
putchar('\n');
}
return 0;
}