国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

UVALive - 6525 Attacking rooks

2019-11-14 12:10:33
字體:
來源:轉載
供稿:網友

2017寒假集訓 3-D

UVALive - 6525 Attacking rooks

二分圖匹配

傳送門:HUSTOJ

傳送門:ACM-ICPC live


題意

象棋盤,‘.’代表兵,‘X’代表車,就是可以攻擊同行或同列的任何棋子(要求中間沒有兵)。 給你一個n*n的象棋盤,問你最多可以放多少個車,使得他們不相互攻擊。


思路

之前看過的題。整理一下思路和教訓,補一發題解紀念一下吧。。

既然是每行每列攻擊,那么把每行每列拆開。將每行中連續為.的作為X集合中一個點,同樣,將每列中連續為.的點作為Y集合中的一個點。對原圖中每個’.’,將其對應的X集合和Y集合中的標號建邊,便形成了二分圖。對該圖求最大匹配,每形成一個匹配即選擇XY中的行列對應的點放車,那么與它相同編號的行和列都被覆蓋了,都不能被選擇了。最大匹配數就是最多可以放的車數。

附一個帶圖的教程。%%%


代碼

可惜我不會KM算法,網絡流解的

WA好幾發,因為生成y的點序號時遍歷ij搞錯了。。。mdzz

#include<cstdio>#include<cstdlib>#include<iostream>#include<algorithm>#include<string>#include<cstring>#include<vector>#include<cmath>#include<queue>using namespace std;const int MAXN=200020;const int oo=0x3f3f3f3f;typedef long long LL;const LL loo=4223372036854775807ll;struct Dinic{ struct Edge{ int from, to, cap, flow;//cap容量 flow流量 Edge(){} Edge(int u, int v, int c, int f){ from=u;to=v;cap=c;flow=f; } }; vector<Edge> edges;//順序的插入邊 vector<int> G[MAXN];//保存邊號 bool vis[MAXN];//BFS使用 int d[MAXN]; int cur[MAXN]; void init(int n) { for(int i=0;i<n;i++) G[i].clear(); edges.clear(); } void AddEdge(int from, int to, int cap) { edges.push_back(Edge(from, to, cap, 0)); edges.push_back(Edge(to, from, 0, 0));//單向邊第三個參數寫0,雙向邊寫cap int t_m=edges.size(); G[from].push_back(t_m-2); G[to].push_back(t_m-1); } bool BFS(int s, int t) { memset(vis, 0, sizeof(vis)); queue<int> Q; Q.push(s); d[s]=0; vis[s]=1; while(!Q.empty()) { int x=Q.front();Q.pop(); for(int i=0;i<G[x].size();i++) { Edge& e=edges[G[x][i]]; if(!vis[e.to]&&e.cap>e.flow)//殘量網絡 { vis[e.to]=1; d[e.to]=d[x]+1; Q.push(e.to); } } } return vis[t]; } int DFS(int x, int a, int s, int t) { if(x==t||a==0) return a; int flow=0, _f; for(int& i=cur[x];i<G[x].size();i++) { Edge& e=edges[G[x][i]]; if(d[x]+1==d[e.to]&&(_f=DFS(e.to, min(a, e.cap-e.flow), s, t))>0) { e.flow+=_f; edges[G[x][i]^1].flow-=_f; flow+=_f; a-=_f; if(a==0) break; } } return flow; } int Maxflow(int s, int t) { int flow=0; while(BFS(s, t)) { memset(cur, 0, sizeof(cur)); flow+=DFS(s, oo, s, t); } return flow; }};Dinic dinic;int main(){ char mp[105][105]; int xmp[105][105]; int ymp[105][105]; int n; while(cin>>n) { dinic.init(200020); memset(mp, 0, sizeof(mp)); memset(xmp, 0, sizeof(xmp)); memset(ymp, 0, sizeof(ymp)); for(int i=0;i<n;i++) { scanf("%s",mp[i]); } int cnt=0, mx=0;; for(int i=0;i<n;i++) { for(int j=0;j<n;j++) { if(mp[i][j]=='.') { if(j!=0&&mp[i][j]==mp[i][j-1]) { xmp[i][j]=cnt; } else { xmp[i][j]=(++cnt); } mx=cnt; } } } int my=0; for(int i=0;i<n;i++) { for(int j=0;j<n;j++) { if(mp[j][i]=='.') { if(j!=0&&mp[j][i]==mp[j-1][i]) { ymp[j][i]=cnt; } else { ymp[j][i]=(++cnt); } my=cnt; } } } const int sup_s=cnt+1; const int sup_t=cnt+2; for(int i=1;i<=mx;i++) { dinic.AddEdge(sup_s, i, 1); } for(int i=mx+1;i<=my;i++) { dinic.AddEdge(i, sup_t, 1); } for(int i=0;i<n;i++) { for(int j=0;j<n;j++) { if(mp[i][j]=='.') { dinic.AddEdge(xmp[i][j], ymp[i][j], 1); //cout<<xmp[i][j]<<' '<<ymp[i][j]<<endl; } } } int fl=dinic.Maxflow(sup_s, sup_t); cout<<fl<<endl; } //system("pause"); return 0;}
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 宜宾县| 子长县| 江山市| 兰西县| 博湖县| 静安区| 营口市| 灵璧县| 弥渡县| 静海县| 化隆| 图们市| 甘南县| 岑溪市| 安丘市| 望奎县| 南陵县| 阿鲁科尔沁旗| 中方县| 庆安县| 岚皋县| 乌拉特前旗| 海原县| 乐业县| 巴塘县| 黄陵县| 白城市| 永吉县| 那坡县| 仲巴县| 景德镇市| 赤壁市| 盘山县| 甘谷县| 金坛市| 重庆市| 海安县| 旬邑县| 清涧县| 泾川县| 五寨县|