zoukankan      html  css  js  c++  java
  • CSUOJ 1319 CX‘s dreams

    一看到这个题就知道是最大闭合子图了,关于最大闭合子图的定义和建图,都是看胡伯涛的论文上的。这里有两问,首先是要求闭合图权最大,第二问,也是比较有难度的就是在闭合图权最大的条件下,尽量多的让dream所代表的点出现在最大权闭合图的闭合图中。最大闭合图是最小割模型的一个应用。由于一个流网络的最小割可能不唯一,所以最大闭合图也不一定是唯一的,所以第二问的难度就增加了。

    这里的解决方法是借助偏移量来维护两个量,一个是最大流,一个是用到的点数。由题意可得,图中点数最多将达到2002,那么现在选择一个MOD=3000的偏移量。首先要统计图中所有点权为正的点的权和sum。建图的时候,对于每个价值为value的dream,从源点S到dream点连一条流量cap=MOD*value+1的边。这里的+1就表示我选了这个点了,如果这条边在最小割中的话,这个+1就一定会在最后体现出来。对于每个价值为value的付出(用点i表示),若value>=0,加边(S,i,value*MOD);value<0,加边(i,T,-value*MOD)。对原图中所有的有向边,加边(i,j,INF)。跑最大流,得到maxflow。那么根据最大闭合子图的解法,最大闭合子图权=sum-maxflow/MOD,可以完成的梦想=总梦想数n-maxflow%MOD;

    命题人ZZY的灵感来自于POJ2987,也是一道最大闭合子图的题目。他的题解在这里:http://blog.csdn.net/kk303/article/details/11843169

    至于他的那个建图为什么是对的,或者说可以过,他和我都晕了。

      1 #include <iostream> 
      2 #include <cstdio> 
      3 #include <cstring> 
      4 #include <algorithm> 
      5 using namespace std; 
      6 typedef long long LL; 
      7 #define INF ((LL)2000000007)*((LL)2000000007) 
      8 #define maxn 2010 
      9 #define maxm 200000 
     10 #define MOD 3000 
     11 int u[maxm],v[maxm],next[maxm]; 
     12 LL w[maxm]; 
     13 int first[maxn],d[maxn],work[maxn],q[maxn]; 
     14 int e,S,T; 
     15 int n,m; 
     16   
     17 void init(){ 
     18     memset(first,-1,sizeof(first)); 
     19     e = 0; 
     20 } 
     21   
     22 void add_edge(int a,int b,LL c){ 
     23     //printf("add:from %d to %d,cap = %lld
    ",a,b,c); 
     24     u[e] = a;v[e] = b;next[e] = first[a];w[e] = c;first[a] = e++; 
     25     u[e] = b;v[e] = a;next[e] = first[b];w[e] = 0;first[b] = e++; 
     26 } 
     27   
     28 int bfs(){ 
     29     int rear = 0; 
     30     memset(d,-1,sizeof(d)); 
     31     d[S] = 0;q[rear++] = S; 
     32     for(int i = 0;i < rear;i++){ 
     33         for(int j = first[q[i]];j != -1;j = next[j]) 
     34             if(w[j] && d[v[j]] == -1){ 
     35                 d[v[j]] = d[q[i]] + 1; 
     36                 q[rear++] = v[j]; 
     37                 if(v[j] == T)   return 1; 
     38             } 
     39     } 
     40     return 0; 
     41 } 
     42   
     43 LL dfs(int cur,LL a){ 
     44     if(cur == T)    return a; 
     45     for(int &i = work[cur];i != -1;i = next[i]) 
     46         if(w[i] && d[v[i]] == d[cur] + 1) 
     47             if(LL t = dfs(v[i],min(a,w[i]))){ 
     48                 w[i] -= t;w[i^1] += t; 
     49                 return t; 
     50             } 
     51     return 0; 
     52 } 
     53   
     54 LL dinic(){ 
     55     LL ans = 0; 
     56     while(bfs()){ 
     57         memcpy(work,first,sizeof(first)); 
     58         while(LL t = dfs(S,INF))   ans += t; 
     59     } 
     60     return ans; 
     61 } 
     62   
     63 int main() 
     64 { 
     65     while(scanf("%d%d",&n,&m) != EOF){ 
     66         init(); 
     67         S = 0,T = n+m+1; 
     68         int sum = 0; 
     69         for(int i = 1;i <= n;i++){ 
     70             int value; 
     71             scanf("%d",&value); 
     72             add_edge(S,i,value*MOD + 1); 
     73             sum += value; 
     74         } 
     75         for(int i = 1;i <= m;i++){ 
     76             int value; 
     77             scanf("%d",&value); 
     78             if(value >= 0)  add_edge(S,i+n,value*MOD),sum += value; 
     79             else            add_edge(i+n,T,-value*MOD); 
     80         } 
     81         for(int i = 1;i <= n;i++){ 
     82             int t; 
     83             scanf("%d",&t); 
     84             while(t--){ 
     85                 int tmp; 
     86                 scanf("%d",&tmp); 
     87                 add_edge(i,n + tmp,INF); 
     88             } 
     89         } 
     90         LL maxflow = dinic(); 
     91         //printf("maxflow = %lld
    ",maxflow); 
     92         printf("%lld %lld
    ",sum - maxflow/MOD,n - maxflow%MOD); 
     93     } 
     94     return 0; 
     95 } 
     96   
     97 /************************************************************** 
     98     Problem: 1319 
     99     User: 1234 
    100     Language: C++ 
    101     Result: Accepted 
    102     Time:164 ms 
    103     Memory:5420 kb 
    104 ****************************************************************/
    View Code
  • 相关阅读:
    Unity3D学习笔记(十九):UGUI、Image、Text、Button
    Unity3D学习笔记(十八):动画内容补充
    Unity3D学习笔记(十七):IK动画、粒子系统和塔防
    Unity3D学习笔记(十六):Animator新动画
    Unity3D学习笔记(十五):寻路系统
    Unity3D学习笔记(十四):Animation旧动画
    Unity3D学习笔记(十三):委托、考试复习
    Unity3D学习笔记(十二):2D模式和异步资源加载
    加密解密
    linux 常用命令
  • 原文地址:https://www.cnblogs.com/zhexipinnong/p/3349600.html
Copyright © 2011-2022 走看看