https://cn.vjudge.net/problem/HDU-2121
题解:首都在的地方在进行朱刘算法的时候注意不要改变边的序号。
代码:
#include <iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
const int inf =0x3f3f3f3f;
const int maxn = 1205;
const int maxm =20005;
struct node{
int u,v,w;
};
node e[maxm];
int pre[maxn],id[maxn],visit[maxn],in[maxn];
int pos;
int zhuliu(int root,int n,int m){
int res=0;
int u,v;
int i;
while(true){
for(i=0;i<n;i++)in[i]=inf;//初始化
//寻找每个点最小的入边
for(i=0;i<m;i++){
if(e[i].u!=e[i].v&&e[i].w<in[e[i].v]){
pre[e[i].v]=e[i].u;
in[e[i].v]=e[i].w;
if(e[i].u==root)pos=i;
}
}
//如果有点没有入边,那么树形图不存在
for(i=0;i<n;i++){
if(in[i]==inf&&i!=root)return -1;
}
int tn=0;
memset(id,-1,sizeof(id));
memset(visit,-1,sizeof(visit));
in[root]=0;
//查环
for(i=0;i<n;i++){
res+=in[i];
v=i;
while(visit[v]!=i&&id[v]==-1&&v!=root){
visit[v]=i;
v=pre[v];
}
if(v!=root&&id[v]==-1){
for(u=pre[v];u!=v;u=pre[u])id[u]=tn;
id[v]=tn++;
}
}
if(tn==0)break;//no loop
for(i=0;i<n;i++)if(id[i]==-1)id[i]=tn++;
for(i=0;i<m;i++){
v=e[i].v;
e[i].u=id[e[i].u];
e[i].v=id[e[i].v];
if(e[i].u!=e[i].v)e[i].w-=in[v];
//else swap(e[i],e[--m]);
}
n=tn;
root=id[root];
}
return res;
}
/
int x[maxn],y[maxn];
double len(int i,int j){
return sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
}
int n,m;
int main()
{
int i;
int sum=0;
int tmp;
while(~scanf("%d%d",&n,&m)){
sum=0;
tmp=m;
n++;
for(i=0;i<m;i++){
scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
sum+=e[i].w;
}
for(i=0;i<n-1;i++){
e[m].u=n-1;
e[m].v=i;
e[m].w=sum+1;
m++;
}
int ans=zhuliu(n-1,n,m);
if(ans>=(2*sum+2))printf("impossible\n");
else printf("%d %d\n",ans-sum-1,pos-tmp);
printf("\n");
}
// cout << "Hello world!" << endl;
return 0;
}