zoukankan      html  css  js  c++  java
  • [SHOI2007]善意的投票

    嘟嘟嘟

     

    看数据范围,加上题中频繁提到的冲突,就可以想到算法是最小割。

    1.同意睡觉的,源点就像他连一条容量为1的边。割掉它就代表他背叛了自己的意愿。

    2.同理,不同意睡觉的,就像汇点连一条边。

    3.考虑每一对朋友。如果两个朋友意见相反,就互相连一条容量为1的边,割掉其中的任意一条就代表朋友之间发生了冲突,代价为1.而且根据网络流性质,一定不会同时割掉这两条边。

    4.如果一对朋友之间意见相同呢?其实还是建边还是和上面一样。因为如果割掉这条边的原因一定是其中一个人为了照顾和自己意见相反的其他朋友,而和这个朋友发生了冲突。

    画一个图:

     

    1,2同意睡觉,且是朋友;3,4不同意睡觉;并且1和3,1和4还是朋友。

    最小割为2,可以有这么几个典型情况:

    1.割掉边(6), (7):3和4为了照顾1,变卦了。

    2.割掉边(4), (5):1分别和3, 4发生冲突。

    3.割掉边(1), (3):1为了照顾3和4,变卦了,因此与2发生了冲突。

    放代码啦:

      1 #include<cstdio>
      2 #include<iostream>
      3 #include<cmath>
      4 #include<algorithm>
      5 #include<cstring>
      6 #include<cstdlib>
      7 #include<cctype>
      8 #include<vector>
      9 #include<stack>
     10 #include<queue>
     11 using namespace std;
     12 #define enter puts("") 
     13 #define space putchar(' ')
     14 #define Mem(a, x) memset(a, x, sizeof(a))
     15 #define rg register
     16 typedef long long ll;
     17 typedef double db;
     18 const int INF = 0x3f3f3f3f;
     19 const db eps = 1e-8;
     20 const int maxn = 305;
     21 inline ll read()
     22 {
     23     ll ans = 0;
     24     char ch = getchar(), last = ' ';
     25     while(!isdigit(ch)) {last = ch; ch = getchar();}
     26     while(isdigit(ch)) {ans = ans * 10 + ch - '0'; ch = getchar();}
     27     if(last == '-') ans = -ans;
     28     return ans;
     29 }
     30 inline void write(ll x)
     31 {
     32     if(x < 0) x = -x, putchar('-');
     33     if(x >= 10) write(x / 10);
     34     putchar(x % 10 + '0');
     35 }
     36 
     37 int n, m, t;
     38 
     39 struct Edge
     40 {
     41     int from, to, cap, flow;
     42 };
     43 vector<Edge> edges;
     44 vector<int> G[maxn];
     45 void addEdge(int from, int to)
     46 {
     47     edges.push_back((Edge){from, to, 1, 0});
     48     edges.push_back((Edge){to, from, 0, 0});
     49     int sz = edges.size();
     50     G[from].push_back(sz - 2);
     51     G[to].push_back(sz - 1);
     52 }
     53 
     54 int dis[maxn];
     55 bool bfs()
     56 {
     57     Mem(dis, 0); dis[0] = 1;
     58     queue<int> q; q.push(0);
     59     while(!q.empty())
     60     {
     61         int now = q.front(); q.pop();
     62         for(int i = 0; i < (int)G[now].size(); ++i)
     63         {
     64             Edge& e = edges[G[now][i]];
     65             if(!dis[e.to] && e.cap > e.flow)
     66             {
     67                 dis[e.to] = dis[now] + 1;
     68                 q.push(e.to);    
     69             }
     70         }
     71     }
     72 //    for(int i = 1; i <= n; ++i) printf("%d ", dis[t]); enter;
     73     return dis[t];
     74 }
     75 int cur[maxn];
     76 int dfs(int now, int res)
     77 {
     78     if(now == t || res == 0) return res;
     79     int flow = 0, f;
     80     for(int& i = cur[now]; i < (int)G[now].size(); ++i)
     81     {
     82         Edge& e = edges[G[now][i]];
     83         if(dis[e.to] == dis[now] + 1 && (f = dfs(e.to, min(res, e.cap - e.flow))) > 0)
     84         {
     85             e.flow += f;
     86             edges[G[now][i] ^ 1].flow -= f;
     87             flow += f; res -= f;
     88             if(res == 0) break;
     89         }
     90     }
     91     return flow;
     92 }
     93 
     94 int minCut()
     95 {
     96     int flow = 0;
     97     while(bfs())
     98     {
     99         Mem(cur, 0);
    100         flow += dfs(0, INF);
    101     }
    102     return flow;
    103 }
    104 
    105 int main()
    106 {
    107     n = read(); m = read();
    108     t = n + 1;
    109     for(int i = 1; i <= n; ++i)
    110     {
    111         int x = read();
    112         if(x) addEdge(0, i);
    113         else addEdge(i, t);
    114     }
    115     for(int i = 1; i <= m; ++i)
    116     {
    117         int x = read(), y = read();
    118         addEdge(x, y); addEdge(y, x);
    119     }
    120     write(minCut()); enter;
    121     return 0;
    122 }
    View Code
  • 相关阅读:
    MongoDB查询修改操作语句命令大全
    SpringBoot读取war包jar包Resource资源文件解决办法
    linux lsof命令详解
    taskset
    POI导出excel,本地测试没问题,linux测试无法导出
    js中文乱码
    处理Account locked due to 217 failed logins的问题
    普通用户无法su到root用户
    gp数据库停止
    eclipse导入maven工程missing artifact(实际是存在的)错误解决
  • 原文地址:https://www.cnblogs.com/mrclr/p/9696426.html
Copyright © 2011-2022 走看看