程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> uva 11248 - Frequency Hopping 最大流最小割入門題 求割集模板

uva 11248 - Frequency Hopping 最大流最小割入門題 求割集模板

編輯:C++入門知識

232/UK44i/334sda#nh$X3y/Appx-301a   At this moment, through out Europe, our base station numbers 1 to N are actively operational through wireless channels. Immediately we require sendingC secret message fragments from our head quarters (base station 1) toNth base station. Germans have developed Zämmhäim– a machine which jams the frequency channel between base stations after a station has sent a message fragment. In that case, the base stations must transmit using a different frequency channel for each message fragment. There are several unidirectional channels set up between base stations at this moment. We can only make arrangements to set up number of frequency channels only between two base stations. Your task is to check whether all the message fragments can be sent to the desired base station with or without increasing frequency channel between any two particular base stations. You have to give us all possible options if it is required to increase frequency channel between two stations.   --End of Attachment       As members of Secret Programmers Group (SPG) you are assigned to solve this problem within 5 hrs and deliver the solution directly toColonel Al Pacheno.You have to maintain Level 3 secrecy and destroy all documents corresponding to this as soon as you deliver the solution.       Input:   There will be multiple test cases. The first line of each test case contains three numbersN, E andC whereN (0<N<101) represents the number of base stations, E (E<10000) represents the number of available connections between the base stations andC (C<2000000000) represents the number of secret message fragments that are required to send from station 1 to station N. After that, there will be E lines. Each line contains 3 numbers:b1(0<b1<101),b2(0<b2<101) andfp (0<fp<5001) which represent the number of frequency channels available currently fromb1 tob2. Input is terminated when N=E=C=0.       Output:   For each test case, there will be one line of output. First, you have to print the case number. If it is possible to sendC secret message fragments from the current status the output will be“possible”. Otherwise, you have to print all pairs of stations (in ascending order) if it is possible send the required message fragments by increasing the frequency channel between any one of them. If it is still impossible, you have to print “not possible”.       Sample Input                            Output for Sample Input 4 4 5   1 2 5   1 3 5   2 4 5   3 4 5   4 4 5   1 2 1   1 3 5   2 4 5   3 4 1   4 4 5   1 2 1   1 3 1   2 4 1   3 4 1   0 0 0                                                                                                                                            Case 1: possible                                                                                                                                        Case 2: possible option:(1,2),(3,4)                                                                                                                                        Case 3: not possible       Problemsetter: Syed Monowar Hossain   Special Thanks: Abdullah al Mahmud   http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&category=24&problem=2205&mosmsg=Submission+received+with+ID+12258596       劉汝佳新書--訓練指南   題意:給定一個有向網絡,每條邊均有一個容量。問是否存在一個從點1到點N,流量為C的流。如果不存在,是否可以恰好修改一條弧的容量,使得存在這樣的流?           分析:先求一次最大流,如果流量至少為C,則直接輸出possible,否則需要修改的弧一定是最小割裡的弧。依次把這些弧的容量增加到C,然後再求最大流,看最大流量是否至少為C即可。 很可惜,這樣寫出來的程序會超時,還需要加兩個重要的優化。第一個優化是求完最大流後把流量留著,以後每次在它的基礎上增廣,第二個優化是每次沒必要求出最大流,增廣到流量至少為C時就停下來。  

 
 
#include<iostream>  
#include<string>  
#include<algorithm>  
#include<cstdlib>  
#include<cstdio>  
#include<set>  
#include<map>  
#include<vector>  
#include<cstring>  
#include<stack>  
#include<cmath>  
#include<queue>  
using namespace std;  
#define CL(x,v); memset(x,v,sizeof(x));  
#define INF 0x3f3f3f3f  
#define LL long long  
#define MAXN 5000  
struct Edge{  
    int from,to,cap,flow;  
};  
  
struct Dinic{  
    int n,m,s,t;  
    vector<Edge> edges;  
    vector<int> G[MAXN];// 鄰接表,G[i][j]表示結點i的第j條邊在e數組中的序號  
    bool vis[MAXN];  
    int d[MAXN];  
    int cur[MAXN];  
    void init(int n){  
        this->n=n;  
        for(int i=0;i<=n;i++)G[i].clear();  
        edges.clear();  
    }  
    void AddEdge(int from,int to,int cap){  
        Edge e;  
        e.from=from;e.to=to;e.cap=cap;e.flow=0;  
        edges.push_back(e);  
        e.from=from;e.to=to;e.cap=0;e.flow=0;  
        edges.push_back(e); m=edges.size();  
        G[from].push_back(m-2);  
        G[to].push_back(m-1);  
    }  
    bool BFS(){  
        CL(vis,0);  
        queue<int> Q;  
        Q.push(s);  
        d[s]=0;  
        vis[s]=1;  
        while(!Q.empty()){  
            int x=Q.front();  
            Q.pop();  
            for(int i=0;i<G[x].size();i++){  
                Edge& e=edges[G[x][i]];  
                if(!vis[e.to]&&e.cap>e.flow){  
                    vis[e.to]=1;  
                    d[e.to]=d[x]+1;  
                    Q.push(e.to);  
                }  
            }  
        }  
        return vis[t];  
    }  
    int DFS(int x,int a){  
        if(x==t||a==0)return a;  
        int flow=0,f;  
        for(int& i=cur[x];i<G[x].size();i++){  
            Edge& e=edges[G[x][i]];  
            if(d[x]+1==d[e.to]&&(f=DFS(e.to,min(a,e.cap-e.flow)))>0){  
                e.flow+=f;  
                edges[G[x][i]^1].flow-=f;  
                flow+=f;  
                a-=f;  
                if(a==0)break;  
            }  
        }  
        return flow;  
    }  
    int Maxflow(int s,int t,int need){//)///求最大流 如果大於need就直接退出  
        this->s=s;this->t=t;  
        int flow=0;  
        while(BFS()){  
            CL(cur,0);  
            flow+=DFS(s,INF);  
            if(flow>need)return flow;  
        }  
        return flow;  
    }  
    // 注意返回類型  
    vector<int> Mincut(){///求最小割集  在求最大流之後才能用,直接用  
        BFS();  
        vector<int> ans;  
        for(int i=0;i<edges.size();i++){  
            Edge& e=edges[i];  
            if(vis[e.from]&&!vis[e.to]&&e.cap>0)ans.push_back(i);  
        }  
        return ans;  
    }  
    void Reduce(){//求剩余容量  
        for(int i = 0; i < edges.size(); i++) edges[i].cap -= edges[i].flow;  
    }  
    void ClearFlow(){//把當前流量flow清0  
        for(int i = 0; i < edges.size(); i++) edges[i].flow = 0;  
    }  
};  
  
  
bool cmp(const Edge& a,const Edge& b){  
    return a.from < b.from || (a.from == b.from && a.to < b.to);  
}  
Dinic solver;///一定要用g++提交 c++編譯錯誤  一定不要忘記調用 init(des)  
int main(){  
    int N,E,C,cas=0;  
    while(~scanf("%d%d%d",&N,&E,&C))  
    {  
        if(!N)break;  
        solver.init(N);  
        int a,b,c;  
        while(E--)  
        {  
            scanf("%d%d%d",&a,&b,&c);  
            solver.AddEdge(a,b,c);  
        }  
        int flow=solver.Maxflow(1,N,INF);  
        printf("Case %d: ",++cas);  
        if(flow>C)printf("possible\n");  
        else{  
            vector<int> cut=solver.Mincut();  
            solver.Reduce();  
            vector<Edge>ans;  
            for(int i=0;i<cut.size();i++){  
                Edge& e=solver.edges[cut[i]];  
                int temp=e.cap;  
                e.cap=C;  
                solver.ClearFlow();  
                if(flow+solver.Maxflow(1,N,C-flow)>=C)ans.push_back(e);  
                e.cap=temp;  
            }  
            if(ans.empty())printf("not possible\n");  
            else{  
                sort(ans.begin(),ans.end(),cmp);  
                printf("possible option:(%d,%d)",ans[0].from,ans[0].to);  
                for(int i=1;i<ans.size();i++)  
                    printf(",(%d,%d)",ans[i].from,ans[i].to);  
                printf("\n");  
            }  
        }  
    }  
    return 0;  
}  

 


  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved