• [ZJOI2007]矩阵游戏


    嘟嘟嘟

    这道题如果不看题解,我是绝对想不到二分图匹配的。

    咱们先不想二分图匹配的事,先想想什么状态是有解的:只要每一行都有一个黑块,且每一个黑块都在不同的一列,那么一定有解。因为即使这些黑块不在主对角线上,我们也可以通过交换行(列)来达到这个最终状态,这就像不断交换两个数来给一个序列排序一样。

    然后考虑建图,每一行作为一个节点,为二分图的左部;每一列也作为一个节点,作为图的右部。如果(i, j)为黑,就给(i, j)连一条边。因为交换任意两行(列)是不会改变图的,可以这么想:每一行的编号不是绝对的,而是最最开始的编号,那么如果把1和3行交换,图上就是把节点1以及他所连的边挪到了3的位置上,3又挪到了1的位置上。

    最后只要判断匹配数是否等于n即可。

      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) memset(a, 0, sizeof(a))
     15 typedef long long ll;
     16 typedef double db;
     17 const int INF = 0x3f3f3f3f;
     18 const db eps = 1e-8;
     19 const int maxn = 405;
     20 inline ll read()
     21 {
     22     ll ans = 0;
     23     char ch = getchar(), last = ' ';
     24     while(!isdigit(ch)) {last = ch; ch = getchar();}
     25     while(isdigit(ch)) {ans = ans * 10 + ch - '0'; ch = getchar();}
     26     if(last == '-') ans = -ans;
     27     return ans;
     28 }
     29 inline void write(ll x)
     30 {
     31     if(x < 0) x = -x, putchar('-');
     32     if(x >= 10) write(x / 10);
     33     putchar(x % 10 + '0');
     34 }
     35 
     36 int t;
     37 
     38 struct Edge
     39 {
     40     int from, to, cap, flow;
     41 };
     42 vector<Edge> edges;
     43 vector<int> G[maxn];
     44 void addEdge(int from, int to)
     45 {
     46     edges.push_back((Edge){from, to, 1, 0});
     47     edges.push_back((Edge){to, from, 0, 0});
     48     int sz = edges.size();
     49     G[from].push_back(sz - 2);
     50     G[to].push_back(sz - 1);
     51 }
     52 
     53 void init()
     54 {
     55     edges.clear(); 
     56     for(int i = 0; i < maxn; ++i) G[i].clear();
     57 }
     58 
     59 int dis[maxn];
     60 bool bfs()
     61 {
     62     Mem(dis); dis[0] = 1;
     63     queue<int> q; q.push(0);
     64     while(!q.empty())
     65     {
     66         int now = q.front(); q.pop();
     67         for(int i = 0; i < (int)G[now].size(); ++i)
     68         {
     69             Edge& e = edges[G[now][i]];
     70             if(!dis[e.to] && e.cap > e.flow)
     71             {
     72                 dis[e.to] = dis[now] + 1;
     73                 q.push(e.to);
     74             }
     75         }
     76     }
     77     return dis[t];
     78 }
     79 int cur[maxn];
     80 int dfs(int now, int res)
     81 {
     82     if(now == t || res == 0) return res;
     83     int flow = 0, f;
     84     for(int& i = cur[now]; i < (int)G[now].size(); ++i)
     85     {
     86         Edge& e = edges[G[now][i]];
     87         if(dis[e.to] == dis[now] + 1 && (f = dfs(e.to, min(res, e.cap - e.flow))) > 0)
     88         {
     89             e.flow += f;
     90             edges[G[now][i] ^ 1].flow -= f;
     91             flow += f;
     92             res -= f;
     93             if(res == 0) break;
     94         }
     95     }
     96     return flow;
     97 }
     98 
     99 int maxflow()
    100 {
    101     int flow = 0;
    102     while(bfs())
    103     {
    104         Mem(cur);
    105         flow += dfs(0, INF);
    106     }
    107     return flow;
    108 }
    109 
    110 int main()
    111 {
    112     int T = read();
    113     while(T--)
    114     {
    115         init();
    116         int n = read(); t = n + n + 1;
    117         for(int i = 1; i <= n; ++i)
    118         {
    119             addEdge(0, i); addEdge(i + n, t);
    120             for(int j = 1; j <= n; ++j) if(read()) addEdge(i, j + n);
    121         }
    122         printf("%s
    ", maxflow() == n ? "Yes" : "No");
    123     }
    124     return 0;
    125 }
    View Code
  • 相关阅读:
    C# Debugger.IsAttached 调试启动浏览器 VS if DEBUG 启动调试内容
    【转载】如何三个月从零基础到C#中级程序员
    【转载】如何成为一个高级程序员
    如何找回QQ聊天记录、语音、图片?
    hexo博客yili主题个性化自定义教程(1) ——借鉴中学习,初认yili主题
    2019hexo博客部署到coding该绕的坑-奥怪的小栈
    2019Hexo博客Next主题深度美化 打造一个炫酷博客(2)-奥怪的小栈
    2019软件工程专业大学排名附官网-奥怪的小栈
    浅谈互联网+足球
    2019基于Hexo快速搭建个人博客,打造一个炫酷博客(1)-奥怪的小栈
  • 原文地址:https://www.cnblogs.com/mrclr/p/9579880.html
Copyright © 2020-2023  润新知