zoukankan      html  css  js  c++  java
  • uva 1349 Optimal Bus Route Design(拆点,费用流)

    题目链接

    题意:给出(n(1 leq n leq 100))个点,每个点与其他一些点相连,边上有权值,现在需要选一些边将所有点包括在一个环内(有且仅有一个环包含每个点,可以有多个环),使得所选边权值之和最小。

    题解:对于每个点存在唯一环包括他,等价于每个点存在唯一后继,对于唯一性,可以想到二分图,将原来每个点拆为两个点,然后加个源和汇s,t,在将边权转化为费用跑费用流就行了。

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<vector>
    #include<queue>
    #include<stack>
    using namespace std;
    #define rep(i,a,n) for (int i=a;i<n;i++)
    #define per(i,a,n) for (int i=n-1;i>=a;i--)
    #define pb push_back
    #define fi first
    #define se second
    typedef vector<int> VI;
    typedef long long ll;
    typedef pair<int,int> PII;
    const int inf=0x3fffffff;
    const ll mod=1000000007;
    const int MAXN =200+10;
    const int MAXM = 21000;
    const int INF = 1e9;
    struct Edge
    {
        int to,next,cap,flow,cost;
    }edge[MAXM];
    int head[MAXN],tol;
    int pre[MAXN],dis[MAXN];
    bool vis[MAXN];
    int N;//节点总个数,节点编号从0~N-1
    
    void addedge(int u,int v,int cap,int cost)
    {
        edge[tol].to = v;edge[tol].cap = cap;edge[tol].cost = cost;edge[tol].flow = 0;
        edge[tol].next = head[u];head[u] = tol++;
        edge[tol].to = u;edge[tol].cap = 0;edge[tol].cost = -cost;edge[tol].flow = 0;
        edge[tol].next = head[v];head[v] = tol++;
    }
    
    
    bool spfa(int s,int t)
    {
        queue<int> q;
        for(int i = 0;i < N;i++)
        {
            dis[i] = INF;
            vis[i] = false;
            pre[i] = -1;
        }
        dis[s] = 0;
        vis[s] = true;
        q.push(s);
        while(!q.empty())
        {
            int u = q.front();
            q.pop();
            vis[u] = false;
            for(int i = head[u]; i != -1;i = edge[i].next)
            {
                int v = edge[i].to;
                if(edge[i].cap > edge[i].flow &&
                   dis[v] > dis[u] + edge[i].cost )
                {
                    dis[v] = dis[u] + edge[i].cost;
                    pre[v] = i;
                    if(!vis[v])
                    {
                        vis[v] = true;
                        q.push(v);
                    }
                }
            }
        }
        if(pre[t] == -1)return false;
        else return true;
    }
    //返回的是最大流,cost存的是最小费用
    int minCostMaxflow(int s,int t,int &cost)
    {
        int flow = 0;
        cost = 0;
        while(spfa(s,t))
        {
            int Min = INF;
            for(int i = pre[t];i != -1;i = pre[edge[i^1].to])
            {
                if(Min > edge[i].cap - edge[i].flow)
                    Min = edge[i].cap - edge[i].flow;
            }
            for(int i = pre[t];i != -1;i = pre[edge[i^1].to])
            {
                edge[i].flow += Min;
                edge[i^1].flow -= Min;
                cost += edge[i].cost * Min;
            }
            flow += Min;
        }
        return flow;
    }
    
    
    int main()
    {
        int n;
        while(~scanf("%d",&n)&&n)
        {
            int st=0,ed=2*n+1;
            N=ed+1;
            tol=0;
            rep(i,0,ed+1) head[i]=-1;
            rep(i,1,n+1)
            {
                int p;
                while(~scanf("%d",&p))
                {
                    if(!p) break;
                    int w;
                    scanf("%d",&w);
                    addedge(i,n+p,1,w);
                }
            }
            rep(i,1,n+1) addedge(st,i,1,0),addedge(n+i,ed,1,0);
            int cost=0;
            int t=minCostMaxflow(st,ed,cost);
            if(t<n) puts("N");
            else printf("%d
    ",cost);
        }
        return 0;
    }
    
  • 相关阅读:
    phpcms后台进入地址(包含No permission resources错误)
    phpmyadmin上传大sql文件办法
    ubuntu彻底卸载mysql
    Hdoj 2602.Bone Collector 题解
    一篇看懂词向量
    Hdoj 1905.Pseudoprime numbers 题解
    The Python Challenge 谜题全解(持续更新)
    Hdoj 2289.Cup 题解
    Hdoj 2899.Strange fuction 题解
    Hdoj 2199.Can you solve this equation? 题解
  • 原文地址:https://www.cnblogs.com/tarjan/p/7350804.html
Copyright © 2011-2022 走看看