以洛谷P4716为例(有定根)
#include<bits/stdc++.h>
#define ll long long
#define IO ios::sync_with_stdio(false);cin.tie(0);
using namespace std;
const int M=1e6+5;
const int N=1e6+5;
const int inf=2e9;
struct Edge
{
int u,v,w;
} e[M];
int n,m,root;
int pre[N],ine[N];
int vis[N],id[N];
int zhuliu(int root)
{
int ans=0;
while(1)
{
for(int i=1;i<=n;i++) ine[i]=inf; // 初始化
for(int i=1;i<=m;i++)
{
int u=e[i].u,v=e[i].v;
if(u!=v&&e[i].w<ine[v]) // 遍历所有边,对每个点找最小的入边
ine[v]=e[i].w,pre[v]=u;
}
for(int i=1;i<=n;i++) //判定无解
if(i!=root&&ine[i]==inf) return -1;
int cnt=0;
for(int i=1;i<=n;i++) vis[i]=id[i]=0;
for(int i=1;i<=n;i++)
{
if(i==root) continue;
ans+=ine[i];
int v=i;
while(vis[v]!=i&&!id[v]&&v!=root) // 找环
{
vis[v]=i;
v=pre[v];
}
if(!id[v]&&v!=root)
{
id[v]=++cnt; // 把环上的点标记为同一点
for(int u=pre[v]; u!=v; u=pre[u])
id[u]=cnt;
}
}
if(cnt==0) break; // 无环,得到解
for(int i=1;i<=n;i++)
if(!id[i]) id[i]=++cnt;
for(int i=1;i<=m;i++)
{
int u=e[i].u,v=e[i].v;
e[i].u=id[u],e[i].v=id[v];
if(id[u]!=id[v]) e[i].w-=ine[v]; //修改边权
}
root=id[root];
n=cnt;
}
return ans;
}
int main(){
cin>>n>>m>>root;
for(int i=1;i<=m;i++){
cin>>e[i].u>>e[i].v>>e[i].w;
}
cout<<zhuliu(root)<<endl;
}
hdu2121无定根的:
#include<bits/stdc++.h>
#define ll long long
#define IO ios::sync_with_stdio(false);cin.tie(0);
using namespace std;
const int M=1e5+1e4+5;
const int N=1e3+5;
const ll inf=1e17;
struct Edge
{
int u,v,w;
} e[M];
int n,m,root,minroot;
int pre[N];ll ine[N];
int vis[N],id[N];
ll zhuliu(int root)
{
ll ans=0;
while(1)
{
for(int i=0;i<=n;i++) ine[i]=inf;
for(int i=1;i<=m;i++)
{
int u=e[i].u,v=e[i].v;
if(u!=v&&e[i].w<ine[v]){
ine[v]=e[i].w,pre[v]=u;
if(u==root) minroot=i;
}
}
for(int i=0;i<=n;i++)
if(i!=root&&ine[i]==inf) return -1;
int cnt=0;
for(int i=0;i<=n;i++) vis[i]=id[i]=-1;
ine[root]=0;
for(int i=0;i<=n;i++)
{
if(i==root) continue;
ans+=ine[i];
int v=i;
while(vis[v]!=i&&id[v]==-1&&v!=root)
{
vis[v]=i;
v=pre[v];
}
if(id[v]==-1&&v!=root)
{
for(int u=pre[v]; u!=v; u=pre[u]){
id[u]=cnt;
}
id[v]=cnt++;
}
}
if(cnt==0) break;
for(int i=0;i<=n;i++)
if(id[i]==-1) id[i]=cnt++;
for(int i=1;i<=m;i++)
{
int u=e[i].u,v=e[i].v;
e[i].u=id[u],e[i].v=id[v];
if(id[u]!=id[v]) e[i].w-=ine[v];
}
root=id[root];
n=cnt-1;
}
return ans;
}
int main(){
while(cin>>n>>m){
int mm=m;m=m+n;ll SUM=0;
for(int i=1;i<=mm;i++){
int u,v,w;cin>>u>>v>>w;u+=1,v+=1;
e[i].u=u,e[i].v=v,e[i].w=w;SUM+=w;
}
SUM++;
for(int i=mm+1;i<=m;i++){
e[i].u=0,e[i].v=i-mm,e[i].w=SUM;
}
ll res=zhuliu(0);
if(res>=2*SUM||res==-1) cout<<"impossible"<<endl<<endl;
else{
cout<<res-SUM<<" "<<minroot-1-mm<<endl<<endl;
}
}
}