zoukankan      html  css  js  c++  java
  • HDU 3251 Being a Hero(最小割+输出割边)

    Problem Description
    You 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.

    Input
    The 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.

    Output
    For 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
    2
    4 4 2
    1 2 2
    1 3 3
    3 2 4
    2 4 1
    2 3
    4 4
    4 4 2
    1 2 2
    1 3 3
    3 2 1
    2 4 1
    2 3
    4 4

    Sample Output
    Case 1: 3
    1 4
    Case 2: 4
    2 1 3

    题意

    N个城市M条边F个城市,M行每行u,v,w代表破坏u到v需要花费w元,F行u,w代表1不能到城市u获得w元,问你最大利润然后输出破坏的道路编号

    题解

    建立源点S=1,汇点T=n+1,uv连边流量w,uT连边流量w,跑最小割,得到最小花费,用总钱-最小花费就是利润

    输出路径考虑S和T集合,DFS(1)跑出来的是S集合的点,其余都是T集合的点,枚举m条边,如果u输出S集合,v属于T集合,就说明是割边

    代码

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 
      4 const int maxn=1005;
      5 const int maxm=2e5+5;//至少总M*2
      6 const int INF=0x3f3f3f3f;
      7 
      8 int TO[maxm],CAP[maxm],NEXT[maxm],tote;
      9 int FIR[maxn],gap[maxn],cur[maxn],d[maxn],q[400000],vis[maxn],u[maxm],v[maxm];
     10 int n,m,S,T;
     11 
     12 void add(int u,int v,int cap)
     13 {
     14     //printf("i=%d %d %d %d
    ",tote,u,v,cap);
     15     TO[tote]=v;
     16     CAP[tote]=cap;
     17     NEXT[tote]=FIR[u];
     18     FIR[u]=tote++;
     19     
     20     TO[tote]=u;
     21     CAP[tote]=0;
     22     NEXT[tote]=FIR[v];
     23     FIR[v]=tote++;
     24 }
     25 void bfs()
     26 {
     27     memset(gap,0,sizeof gap);
     28     memset(d,0,sizeof d);
     29     ++gap[d[T]=1];
     30     for(int i=1;i<=n;++i)cur[i]=FIR[i];
     31     int head=1,tail=1;
     32     q[1]=T;
     33     while(head<=tail)
     34     {
     35         int u=q[head++];
     36         for(int v=FIR[u];v!=-1;v=NEXT[v])
     37             if(!d[TO[v]])
     38                 ++gap[d[TO[v]]=d[u]+1],q[++tail]=TO[v];
     39     }
     40 }
     41 int dfs(int u,int fl)
     42 {
     43     if(u==T)return fl;
     44     int flow=0;
     45     for(int &v=cur[u];v!=-1;v=NEXT[v])
     46         if(CAP[v]&&d[u]==d[TO[v]]+1)
     47         {
     48             int Min=dfs(TO[v],min(fl,CAP[v]));
     49             flow+=Min,fl-=Min,CAP[v]-=Min,CAP[v^1]+=Min;
     50             if(!fl)return flow;
     51         }
     52     if(!(--gap[d[u]]))d[S]=n+1;
     53     ++gap[++d[u]],cur[u]=FIR[u];
     54     return flow;
     55 }
     56 int ISAP()
     57 {
     58     bfs();
     59     int ret=0;
     60     while(d[S]<=n)ret+=dfs(S,INF);
     61     return ret;
     62 }
     63 void init()
     64 {
     65     tote=0;
     66     memset(FIR,-1,sizeof FIR);
     67 }
     68 void dfs(int u)
     69 {
     70     for(int i=FIR[u];i!=-1;i=NEXT[i])
     71     {
     72         int v=TO[i];
     73         if(CAP[i]!=0&&!vis[v])
     74         {
     75             vis[v]=true;
     76             dfs(v);
     77         }
     78     }
     79 }
     80 int main()
     81 {
     82     int t,f,o=1;
     83     scanf("%d",&t);
     84     while(t--)
     85     {
     86         init();
     87         scanf("%d%d%d",&n,&m,&f);
     88         for(int i=0,w;i<m;i++)
     89         {
     90             scanf("%d%d%d",&u[i],&v[i],&w);
     91             add(u[i],v[i],w);
     92         }
     93         S=1,T=n+1,n+=1;
     94         add(S,1,INF);
     95         int sum=0;
     96         for(int i=0,uu,w;i<f;i++)
     97         {
     98             scanf("%d%d",&uu,&w);
     99             add(uu,T,w);
    100             sum+=w;
    101         }
    102         printf("Case %d: %d
    ",o++,sum-ISAP());
    103         
    104         memset(vis,0,sizeof vis);
    105         dfs(1);
    106         vector<int>ans;
    107         for(int i=0;i<m;i++)
    108             if(vis[u[i]]&&!vis[v[i]])
    109                 ans.push_back(i+1);
    110         printf("%d",(int)ans.size());
    111         for(int i=0;i<ans.size();i++)
    112             printf(" %d",ans[i]);
    113         printf("
    ");
    114     }
    115     return 0;
    116 }
  • 相关阅读:
    JVM常用参数整理
    mac系统使用Chrome浏览器https不自动保存密码
    JVM和JMM内存模型
    Chrome提示是否保存密码点击了否,导致没有自动保存密码
    解决Mac系统IDEA debug卡顿问题
    DBeaver的时区问题
    IDEA导航光标回退和前进快捷键失效
    Dubbo 2.6.0升级到2.7.3
    chrome浏览器备忘
    电脑导入mobi书籍文件到IPAD的方法
  • 原文地址:https://www.cnblogs.com/taozi1115402474/p/9608631.html
Copyright © 2011-2022 走看看