HDU2121 Ice_cream’s world II (最小树形图)

在建图的时候对原图进行加边 建立一个超级源点~

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=1014;
const int maxm=10014;
const int inf=1e9;
struct edge {
    int u;
    int v;
    int w;
}Edge[maxm];
int pre[maxn];
int id[maxn];
int visit[maxn];
int in[maxn];
int N,M;
int root;
int pos;
int num;
void add (int u,int v,int w) {
    Edge[num].u=u;
    Edge[num].v=v;
    Edge[num++].w=w;
}
int solve () {
    int ans=0;
    while (1) {
        for (int i=0;i<N;i++) in[i]=inf;
        for (int i=0;i<num;i++) {
            int u=Edge[i].u;
            int v=Edge[i].v;
            if (Edge[i].w<in[v]&&u!=v) {
                pre[v]=u;
                in[v]=Edge[i].w;
                if (u==root) pos=i;
            }
        }
        for (int i=0;i<N;i++) {
            if (i!=root&&in[i]==inf) return -1;
        }
        int tn=0;
        memset(id,-1,sizeof(id));
        memset(visit,-1,sizeof(visit));
        in[root]=0;
        for (int i=0;i<N;i++) {
            ans+=in[i];
            int v=i;
            while (visit[v]!=i&&id[v]==-1&&v!=root) {
                visit[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<num;i++) {
            int 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].w-=in[v];
        }
        N=tn;
        root=id[root];
    }
    return ans;
}
int main () {
    while (~scanf("%d%d",&N,&M)) {
        int sum=0;
        num=0;
        for (int i=0;i<M;i++) {
            int u,v,w;
            scanf ("%d %d %d",&u,&v,&w);
            sum+=w;
            add(u,v,w); 
        }
        sum++;
        for (int i=0;i<N;i++) {
            add(N,i,sum);
        }
        N++;
        root=N-1;
        int ans=solve();
        if (ans==-1||ans>=2*sum) {
            printf ("impossible\n");
        }
        else printf ("%d %d\n",ans-sum,pos-M);
        printf ("\n");
    }
    return 0;
}

 

posted @ 2020-02-23 20:27  zlc0405  阅读(98)  评论(0编辑  收藏  举报