ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[ZJOI2007]矩阵游戏

2021-05-29 19:03:54  阅读:216  来源: 互联网

标签:include 游戏 int 矩阵 flow edges ZJOI2007 now dis


嘟嘟嘟

 

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

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

然后考虑建图,每一行作为一个节点,为二分图的左部;每一列也作为一个节点,作为图的右部。如果(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\n", maxflow() == n ? "Yes" : "No");
123     }
124     return 0;
125 }
View Code

 

标签:include,游戏,int,矩阵,flow,edges,ZJOI2007,now,dis
来源: https://blog.51cto.com/u_15234622/2830922

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有