日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

[清华集训2017]无限之环(网络流)

發(fā)布時(shí)間:2023/12/3 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [清华集训2017]无限之环(网络流) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

很妙的一道題

對(duì)于每個(gè)格子,它合法與否,只跟它上下左右的相鄰格子有關(guān),所以可以想到黑白染色
(用 (i,j) 表示 i 行 j 列的格子,我把 (i+j) %2 == 0 的格子染成白色,把(i+j)%2 == 1 的格子染成黑色)

關(guān)鍵是怎么描述旋轉(zhuǎn)操作

我樸實(shí)的想法是給每個(gè)格子建四個(gè)點(diǎn),每個(gè)點(diǎn)代表格子可通過(guò)旋轉(zhuǎn)達(dá)到的一種狀態(tài),從格子的初始狀態(tài)向格子其它狀態(tài)連邊,然后把格子間可以匹配的狀態(tài)連起來(lái),再然后……就沒(méi)有然后了

看了題解,真的被驚到了
還是把每個(gè)格子拆成4個(gè)節(jié)點(diǎn),對(duì)應(yīng)四個(gè)方向上的接口
從源點(diǎn)向白格的接口連流量上界1,費(fèi)用0的邊
從黑格的接口向匯點(diǎn)連流量上界1,費(fèi)用0的邊
從黑格的接口向可以匹配的白格的接口連流量上界1,費(fèi)用0的邊
然后旋轉(zhuǎn)操作,就可以通過(guò)一種神奇方式描述出來(lái):

AD O BC

把這個(gè)看成一個(gè)白格(黑格類似,只是連邊方向相反)
邊(u->v,f,w)代表從 u 到 v,流量上界 f,費(fèi)用 w 的邊
下文描述的旋轉(zhuǎn)方向均為順時(shí)針
1.此格有1個(gè)接口:

A| D O BC

(A->B ,1,1)) 對(duì)應(yīng)轉(zhuǎn)90度
(A->C, 1,2)) 對(duì)應(yīng)轉(zhuǎn)180度
(A->D ,1,1)) 對(duì)應(yīng)轉(zhuǎn)270度
2.此格有2個(gè)接口:
情況1:

A| D O —— BC

(A->C, 1,1)) 對(duì)應(yīng)轉(zhuǎn)90度
(B->D ,1,1)) 對(duì)應(yīng)轉(zhuǎn)270度
(A->C, 1,1))+(B->D ,1,1)) 對(duì)應(yīng)轉(zhuǎn)180度
情況2:

A| D O B|C

不能轉(zhuǎn),忽略
3.此格有3個(gè)接口:

A| D O —— B|C

(A->D ,1,1)) 對(duì)應(yīng)轉(zhuǎn)270度
(B->D, 1,2)) 對(duì)應(yīng)轉(zhuǎn)180度
(C->D ,1,1)) 對(duì)應(yīng)轉(zhuǎn)90度
4.此格有4個(gè)接口:

A| D —— O —— B|C

轉(zhuǎn)了也沒(méi)區(qū)別,忽略

建完圖后跑最小費(fèi)用最大流即可

如果我表達(dá)不清的話,這是樣例1的建圖,很丑,湊合著看吧

圖上標(biāo)的數(shù)代表費(fèi)用,沒(méi)標(biāo)的邊默認(rèn)費(fèi)用為0,所有邊的流量上界默認(rèn)為1

#include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; const int inf=0x7fffffff; const int N=8100; const int M=200010; struct Edge{int u,v,f,w,nxt; }edge[M<<1]; int s,t,head[N],cnt,maxflow,mincost,dis[N],inque[N],pre[N]; queue<int> q; int n,m,id[2005][2005][4],num,gr[2005][2005],tot; void add(int u,int v,int f,int w){edge[cnt].u=u;edge[cnt].v=v;edge[cnt].f=f;edge[cnt].w=w;edge[cnt].nxt=head[u];head[u]=cnt++;edge[cnt].u=v;edge[cnt].v=u;edge[cnt].f=0;edge[cnt].w=-w;edge[cnt].nxt=head[v];head[v]=cnt++; } bool spfa(){memset(dis,0x7f,sizeof(dis));memset(inque,0,sizeof(inque));memset(pre,-1,sizeof(pre));dis[s]=0;q.push(s);inque[s]=1;while(!q.empty()){int u=q.front();q.pop();inque[u]=0;for(int i=head[u];i!=-1;i=edge[i].nxt){int v=edge[i].v;if(edge[i].f>0&&dis[v]>dis[u]+edge[i].w){dis[v]=dis[u]+edge[i].w;pre[v]=i;if(!inque[v]){q.push(v);inque[v]=1;}}}} if(pre[t]!=-1) return 1;return 0; } void EK(){int flow;while(spfa()){flow=inf;int x=pre[t];while(x!=-1){flow=min(edge[x].f,flow);x=pre[edge[x].u];}x=pre[t];while(x!=-1){edge[x].f-=flow;edge[x^1].f+=flow;mincost+=flow*edge[x].w;x=pre[edge[x].u];}maxflow+=flow;} } int main(){memset(head,-1,sizeof(head));scanf("%d%d",&n,&m);for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)for(int k=0;k<4;k++)id[i][j][k]=++num;s=++num,t=++num; for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){scanf("%d",&gr[i][j]);int tt=0,pos[5]={-1,-1,-1,-1,-1},npos=-1;for(int k=0;k<4;k++){if(gr[i][j]&(1<<k)){tot++;pos[++tt]=k;if((i+j)%2==0) add(s,id[i][j][k],1,0);else add(id[i][j][k],t,1,0);}else npos=k;}if(tt==1){if((i+j)%2==0){add(id[i][j][pos[1]],id[i][j][(pos[1]+1)%4],1,1);add(id[i][j][pos[1]],id[i][j][(pos[1]+2)%4],1,2);add(id[i][j][pos[1]],id[i][j][(pos[1]+3)%4],1,1);}else{add(id[i][j][(pos[1]+1)%4],id[i][j][pos[1]],1,1);add(id[i][j][(pos[1]+2)%4],id[i][j][pos[1]],1,2);add(id[i][j][(pos[1]+3)%4],id[i][j][pos[1]],1,1);}}else if(tt==2){if(pos[2]-pos[1]==2) continue;if((i+j)%2==0){add(id[i][j][pos[1]],id[i][j][(pos[1]+2)%4],1,1);add(id[i][j][pos[2]],id[i][j][(pos[2]+2)%4],1,1);}else{add(id[i][j][(pos[1]+2)%4],id[i][j][pos[1]],1,1);add(id[i][j][(pos[2]+2)%4],id[i][j][pos[2]],1,1);}}else if(tt==3){if((i+j)%2==0){add(id[i][j][(npos+1)%4],id[i][j][npos],1,1);add(id[i][j][(npos+2)%4],id[i][j][npos],1,2);add(id[i][j][(npos+3)%4],id[i][j][npos],1,1);}else{add(id[i][j][npos],id[i][j][(npos+1)%4],1,1);add(id[i][j][npos],id[i][j][(npos+2)%4],1,2);add(id[i][j][npos],id[i][j][(npos+3)%4],1,1);}}else continue;}}//一開(kāi)始這一塊的建圖錯(cuò)了 int dx[]={-1,0,1,0};int dy[]={0,1,0,-1};for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){if((i+j)%2==0){for(int k=0;k<=3;k++){int x=i+dx[k],y=j+dy[k];if(x<1||x>n||y<1||y>m) continue;add(id[i][j][k],id[x][y][(k+2)%4],1,0);}}}}EK();if(tot%2!=0||maxflow!=tot/2) printf("-1\n"); //注意還要判斷tot%2!=0的情況 else printf("%d\n",mincost);return 0; }

總結(jié)

以上是生活随笔為你收集整理的[清华集训2017]无限之环(网络流)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。