zoukankan      html  css  js  c++  java
  • 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
    ");
            }
            else printf ("%d %d
    ",ans-sum,pos-M);
            printf ("
    ");
        }
        return 0;
    }
  • 相关阅读:
    MySQL学习(一) 概述
    Spring Tool Suite生成默认的MVC项目的配置文件问题
    [国家集训队]排队
    「PKUSC2018」最大前缀和
    「PKUSC2018」真实排名
    Min-Max容斥 & FMT
    SPOJ-CLFLARR 题解
    FFT详解
    CF Round#446 改题
    [CF1131D]Gourmet Choice 题解
  • 原文地址:https://www.cnblogs.com/zhanglichen/p/12354047.html
Copyright © 2011-2022 走看看