• POJ 3068 "Shortest" pair of paths | 最小费用最大流


    题目:

    给一个有向带权图,问从0到n-1存不存在两条路径保证不存在公共点

    若存在输出最小权值和


    题解:

    先把点编号都++

    S向1连权值为0,容量为2,n向T连权值为0,容量为2的点

    原始图中每条边(u,v)从u向v连权值为边权,容量为1的点

    如果最大流为2就输出最小费用

    否则不存在

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<queue>
    #define N 200100
    #define INF 100000000
    using namespace std;
    int ecnt=1,vis[N],dist[N],n,m,S,T,ans,head[N],Case;
    deque <int> q;
    struct adj
    {
        int nxt,v,w,c;
    }e[N];
    inline void add(int u,int v,int w,int c)
    {
        e[++ecnt].v=v,e[ecnt].w=w,e[ecnt].c=c,e[ecnt].nxt=head[u],head[u]=ecnt;
        e[++ecnt].v=u,e[ecnt].w=0,e[ecnt].c=-c,e[ecnt].nxt=head[v],head[v]=ecnt;
    }
    inline int spfa(int s,int t)
    {
        int v;
        memset(vis,0,sizeof(vis));
        for (int i=s;i<=t;i++) dist[i]=INF;
        dist[t]=0,vis[t]=1;
        q.push_back(t);
        while (!q.empty())
        {
        int u=q.front();q.pop_front();
        for (int i=head[u];i;i=e[i].nxt)
            if (e[i^1].w>0 && dist[v=e[i].v]>dist[u]-e[i].c)
            {
            dist[v]=dist[u]-e[i].c;
            if (!vis[v])
            {
                vis[v]=1;
                if (!q.empty() && dist[v]<dist[q.front()])
                q.push_front(v);
                else
                q.push_back(v);
            }
            }
        vis[u]=0;
        }
        return dist[s]<INF;
    }
    inline int dfs(int x,int flow)
    {
        if (x==T)
        return vis[T]=1,flow;
        int used=0,tmp,v;
        vis[x]=1;
        for (int i=head[x];i;i=e[i].nxt)
        if (!vis[v=e[i].v] && e[i].w>0 && dist[x]-e[i].c==dist[v])
        {
            tmp=dfs(v,min(e[i].w,flow-used));
            if (tmp>0)
            ans+=tmp*e[i].c,e[i].w-=tmp,e[i^1].w+=tmp,used+=tmp;
            if (used==flow) break;
        }
        return used;
    }
    inline int CostFlow()
    {
        int Flow=0;
        while (spfa(S,T))
        {
        vis[T]=1;
        while (vis[T])
        {
            memset(vis,0,sizeof(vis));
            Flow+=dfs(S,INF);
        }
        }
        return Flow;
    }
    void init()
    {
        ans=0;
        memset(head,0,sizeof(head));
        Case++;
        S=0,T=n+1;
    }
    int main()
    {
        while (scanf("%d%d",&n,&m)!=EOF)
        {
    	if (n==0 && m==0) break;
    	init();
    	printf("Instance #%d: ",Case);
    	for (int i=1,u,v,w ;i<=m;i++)
    	{
    	    scanf("%d%d%d",&u,&v,&w);
    	    add(u+1,v+1,1,w);
    	}
    	add(S,1,2,0);
    	add(n,T,2,0);
    	
    	if (CostFlow()==2)
    	    printf("%d
    ",ans);
    	else puts("Not possible");
        }
        return 0;
    }
    
  • 相关阅读:
    输入n个整数,输出其中最小的k个
    输出单向链表中倒数第k个结点
    扑克牌大小
    Optional<T> 避免和null检查相关的bug
    筛选、切片、匹配、查找、匹配、归约
    java8 流 中的常用函数式接口
    action 和 controller 单例与多例问题
    Collections.sort Comparator.comparing 冒泡排序 效率对比
    java8 流
    将逗号分割的列,变成多列
  • 原文地址:https://www.cnblogs.com/mrsheep/p/7953879.html
Copyright © 2020-2023  润新知