hdoj 3251 Being a Hero 【建圖後求解最小割 + 輸出任意一組最小割裡面邊 的編號】

來源:互聯網
上載者:User

標籤:



Being a HeroTime Limit: 20000/10000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1252    Accepted Submission(s): 395
Special Judge


Problem DescriptionYou are the hero who saved your country. As promised, the king will give you some cities of the country, and you can choose which ones to own!

But don‘t get too excited. The cities you take should NOT be reachable from the capital -- the king does not want to accidentally enter your area. In order to satisfy this condition, you have to destroy some roads. What‘s worse, you have to pay for that -- each road is associated with some positive cost. That is, your final income is the total value of the cities you take, minus the total cost of destroyed roads.

Note that each road is a unidirectional, i.e only one direction is available. Some cities are reserved for the king, so you cannot take any of them even if they‘re unreachable from the capital. The capital city is always the city number 1.
 
InputThe first line contains a single integer T (T <= 20), the number of test cases. Each case begins with three integers n, m, f (1 <= f < n <= 1000, 1 <= m < 100000), the number of cities, number of roads, and number of cities that you can take. Cities are numbered 1 to n. Each of the following m lines contains three integers u, v, w, denoting a road from city u to city v, with cost w. Each of the following f lines contains two integers u and w, denoting an available city u, with value w. 
OutputFor each test case, print the case number and the best final income in the first line. In the second line, print e, the number of roads you should destroy, followed by e integers, the IDs of the destroyed roads. Roads are numbered 1 to m in the same order they appear in the input. If there are more than one solution, any one will do. 
Sample Input
24 4 21 2 21 3 33 2 42 4 12 34 44 4 21 2 21 3 33 2 12 4 12 34 4
 
Sample Output
Case 1: 31 4Case 2: 42 1 3
 


犯二了,坐兩個多小時的車。累死啦。/(ㄒoㄒ)/~~


題意:有N個城市(編號從1到N)和串連城市的M條有向邊。你可以選擇F個城市,但要求城市1不能到達這F個城市,因此你需要破壞一些邊。現在給你破壞每條邊的花費以及F個城市的價值,問你能得到的最大價值,並輸出需要破壞的邊數以及該邊的編號(若有多種方案,可以輸出任意一種)。


思路:求最小割,最大價值就是F個城市的總價值-最小割。至於輸出最小割裡面邊的編號,只需在殘量網路裡找到城市1能到達的所有點,這些點必定構成一個集合S。最後遍曆M條有向邊的正向弧,若弧的起點在S集並且終點不在,那麼該弧就是最小割裡面的一條邊。


建圖:設定超級源點source,超級匯點sink

1,有向邊<u, v>建邊,邊權為破壞該邊的花費;

2,source向城市1建邊,容量為無窮大;

3,選擇的F個城市向sink建邊,容量為該城市的價值。

source->sink跑一次最大流 即求出最小割。


AC代碼:

#include <cstdio>#include <cstring>#include <algorithm>#include <queue>#define MAXN 1010#define MAXM 300000+10#define INF 0x3f3f3f3fusing namespace std;struct Edge{    int from, to, cap, flow, ID, next;//ID記錄邊的編號};Edge edge[MAXM];int head[MAXN], edgenum;int dist[MAXN], cur[MAXN];bool vis[MAXN];int N, M, F;int source, sink;void init(){    edgenum = 0;    memset(head, -1, sizeof(head));}void addEdge(int u, int v, int w, int id){    Edge E1 = {u, v, w, 0, id, head[u]};    edge[edgenum] = E1;    head[u] = edgenum++;    Edge E2 = {v, u, 0, 0, id, head[v]};    edge[edgenum] = E2;    head[v] = edgenum++;}int val;//所有能擷取城市的價值void getMap(){   source = 0, sink = N+1;   int a, b, c;   for(int i = 1; i <= M; i++)   {       scanf("%d%d%d", &a, &b, &c);       addEdge(a, b, c, i);//注意是有向邊       //addEdge(b, a, c, i);   }   val = 0;   //M條後 其它的邊都是虛擬邊 預設ID為0   for(int i = 1; i <= F; i++)   {       scanf("%d%d", &a, &c);       val += c;       addEdge(a, sink, c, 0);   }   addEdge(source, 1, INF, 0);//source 向 城市1建邊}bool BFS(int s, int t){    queue<int> Q;    memset(dist, -1, sizeof(dist));    memset(vis, false, sizeof(vis));    dist[s] = 0;    vis[s] = true;    Q.push(s);    while(!Q.empty())    {        int u = Q.front();        Q.pop();        for(int i = head[u]; i != -1; i = edge[i].next)        {            Edge E = edge[i];            if(!vis[E.to] && E.cap > E.flow)            {                dist[E.to] = dist[u] + 1;                if(E.to == t) return true;                vis[E.to] = true;                Q.push(E.to);            }        }    }    return false;}int DFS(int x, int a, int t){    if(x == t || a == 0) return a;    int flow = 0, f;    for(int &i = cur[x]; i != -1; i = edge[i].next)    {        Edge &E = edge[i];        if(dist[E.to] == dist[x] + 1 && (f = DFS(E.to, min(a, E.cap - E.flow), t)) > 0)        {            edge[i].flow += f;            edge[i^1].flow -= f;            flow += f;            a -= f;            if(a == 0) break;        }    }    return flow;}int Maxflow(int s, int t){    int flow = 0;    while(BFS(s, t))    {        memcpy(cur, head, sizeof(head));        flow += DFS(s, INF, t);    }    return flow;}void find_S(int u)//在殘量網路裡面 找源點能到的S集{    for(int i = head[u]; i != -1; i = edge[i].next)    {        Edge E = edge[i];        if(vis[E.to]) continue;        if(E.cap > E.flow)//不能滿流        {            vis[E.to] = true;            find_S(E.to);        }    }}int rec[100000+1];//記錄最小割裡面邊的編號void output(){    int ans = 0;//統計要去掉的邊數    memset(vis, false, sizeof(vis));    find_S(1);//要從1開始    for(int i = 0; i < edgenum; i+=2)//遍曆正向弧    {        if(edge[i].ID == 0)//出現ID為0的邊 意味著M條實邊已經遍曆完了             break;        if(vis[edge[i].from] && !vis[edge[i].to])//起點在S集 終點不在            rec[ans++] = edge[i].ID;//記錄    }    printf("%d", ans);    for(int i = 0; i < ans; i++)        printf(" %d", rec[i]);    printf("\n");}int main(){    int t, k = 1;    scanf("%d", &t);    while(t--)    {        scanf("%d%d%d", &N, &M, &F);        init();        getMap();        printf("Case %d: %d\n", k++, val - Maxflow(source, sink));        output();    }    return 0;}


著作權聲明:本文為博主原創文章,未經博主允許不得轉載。

hdoj 3251 Being a Hero 【建圖後求解最小割 + 輸出任意一組最小割裡面邊 的編號】

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.