zoukankan      html  css  js  c++  java
  • Aizu 2304 Reverse Roads 费用流

    Reverse Roads

    Time Limit: 1 Sec  

    Memory Limit: 256 MB

    题目连接

    http://acm.hust.edu.cn/vjudge/contest/view.action?cid=93265#problem/E

    Description

    ICP city has an express company whose trucks run from the crossing S to the crossing T. The president of the company is feeling upset because all the roads in the city are one-way, and are severely congested. So, he planned to improve the maximum flow (edge disjoint paths) from the crossing S to the crossing T by reversing the traffic direction on some of the roads.

    Your task is writing a program to calculate the maximized flow from S to T by reversing some roads, and the list of the reversed roads.

    Input

    The first line of a data set contains two integers N (2 leq N leq 300) and M (0 leq M leq { m min} (1\,000, N(N-1)/2)). N is the number of crossings in the city and M is the number of roads.

    The following M lines describe one-way roads in the city. The i-th line (1-based) contains two integers X_i and Y_i (1 leq X_i, Y_i leq N,X_i eq Y_i). X_i is the ID number (1-based) of the starting point of the i-th road and Y_i is that of the terminal point. The last line contains two integers S and T (1 leq S, T leq NS eq T1-based).

    The capacity of each road is 1. You can assume that i eq j implies either X_i eq X_j or Y_i eq Y_j, and either X_i eq Y_j or X_j eq Y_i.

    Output

    In the first line, print the maximized flow by reversing some roads. In the second line, print the number R of the reversed roads. In each of the following R lines, print the ID number (1-based) of a reversed road. You may not print the same ID number more than once.

    If there are multiple answers which would give us the same flow capacity, you can print any of them.

    Sample Input

    2 1
    2 1
    2 1

    Sample Output

    1
    0

    HINT

    题意

    给你一个图,然后图的边可以反转,反转的代价为1,问你保证最大流的情况下,使得反转的边最少

    并且把反转的边输出出来

    题解:

    裸的费用流,特别裸……

    代码:

    //qscqesze
    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <ctime>
    #include <iostream>
    #include <algorithm>
    #include <set>
    #include <bitset>
    #include <vector>
    #include <sstream>
    #include <queue>
    #include <typeinfo>
    #include <fstream>
    #include <map>
    #include <stack>
    typedef long long ll;
    using namespace std;
    //freopen("D.in","r",stdin);
    //freopen("D.out","w",stdout);
    #define sspeed ios_base::sync_with_stdio(0);cin.tie(0)
    #define maxn 200500
    #define mod 1001
    #define eps 1e-9
    #define pi 3.1415926
    int Num;
    //const int inf=0x7fffffff;
    const ll inf=999999999;
    inline ll read()
    {
        ll x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    //*************************************************************************************
    const int MAXN = 1000;
    const int MAXM = 150000;
    const int INF = 0x3f3f3f3f;
    struct Edge
    {
        int to, next, cap, flow, cost, id;
        int x, y;
    } edge[MAXM],HH[MAXN],MM[MAXN];
    int head[MAXN],tol;
    int pre[MAXN],dis[MAXN];
    bool vis[MAXN];
    int N, M;
    char map[MAXN][MAXN];
    void init()
    {
        N = MAXN;
        tol = 0;
        memset(head, -1, sizeof(head));
    }
    void addedge(int u, int v, int cap, int cost,int id)//左端点,右端点,容量,花费, 编号
    {
        edge[tol]. to = v;
        edge[tol]. cap = cap;
        edge[tol]. cost = cost;
        edge[tol]. flow = 0;
        edge[tol]. next = head[u];
        edge[tol].id = id;
        head[u] = tol++;
        edge[tol]. to = u;
        edge[tol]. cap = 0;
        edge[tol]. cost = -cost;
        edge[tol]. flow = 0;
        edge[tol]. next = head[v];
        edge[tol].id = id;
        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存的是最小费用
    vector<int> ans;
    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;
    }
    
    vector<int> Q;
    int main()
    {
        init();
        int n=read(),m=read();
        for(int i=0;i<m;i++)
        {
            int x=read(),y=read();
            addedge(x,y,1,0,i+1);
            addedge(y,x,1,1,i+1);
        }
        int s=read(),t=read();
        int ans1 = 0,ans2 = 0;
        ans1 = minCostMaxflow(s,t,ans2);
    
        for(int i=1;i<=n;i++)
        {
            for(int j = head[i]; j != -1; j = edge[j]. next)
            {
                if(edge[j].flow == 1)
                {
                    if(edge[j].cost)
                    {
                        Q.push_back(edge[j].id);
                    }
                }
            }
        }
    
    
        printf("%d
    %d
    ",ans1,ans2);
        for(int i=0;i<Q.size();i++)
            printf("%d
    ",Q[i]);
    }
  • 相关阅读:
    在JS中,一切东东其实都是对象
    Java多维数组
    理解Java主函数中的"String[] args"
    Java中"String.equals()“和"=="的区别
    Java:新建数组
    [BOOKS]BIG DATA and DATA ANALYTICS: The Beginner's Guide to Understanding the Analytical World
    [BOOKS]Big Data: Principles and best practices of scalable realtime data systems
    Update Vim to 8.0 in Ubuntu
    Vim显示/不显示行号
    数组(R语言)
  • 原文地址:https://www.cnblogs.com/qscqesze/p/4851565.html
Copyright © 2011-2022 走看看