To_Heart—題解——[CQOI2017]老C的方塊
阿新 • • 發佈:2021-12-10
這裡提供一種更好想,但是點會多一些的做法
首先我們很容易就能想到染色
染色
我們按照以上方法染色,然後發現從 1 出發,沿著 1->2->3->4 的路線,可以把我們所有需要刪除情況都涵蓋完。
所以我們現在就只需要建圖了
建圖
因為我們可以沿著 1->2->3->4 的路線走完所有的情況,那麼就可以建分層圖了:
那麼圖與圖之間怎麼連邊呢?我們就把一個點相鄰的點,且染色顏色比它大 1 的點和它之間連一條邊,邊權為刪去當前相鄰點的代價。
但是我們直接連邊會出現問題:
就像這張圖一樣,當我們刪去了1和3之間的邊,就相當於刪去的節點3,但我們的2和3還是聯通的,所以就會出現我們的點被刪兩次的情況。
所以我們要拆點,把點的點權轉換為該點的兩個點之間的邊權,把兩層之間的邊權設為極大值就好了。
程式碼
#include<bits/stdc++.h> using namespace std; #define ll long long const int INF=0x3f3f3f3f; struct zz{ int u,w,id; }; vector<zz> v[1000005]; struct Dinic{ int dist[1000005],be[1000005]; int s,t; void Add(int x,int y,int z){ // printf("QwQ:%d %d %d\n",x,y,z); int idx=v[x].size(),idy=v[y].size(); v[x].push_back((zz){y,z,idy}); v[y].push_back((zz){x,0,idx}); } bool BFS(){ bool f=0;memset(dist,-1,sizeof dist); queue<int> q;q.push(s); dist[s]=be[s]=0; while(!q.empty()){ int x=q.front();q.pop(); int siz=v[x].size(); for(int i=0;i<siz;i++){ int y=v[x][i].u,w=v[x][i].w; if(!w||dist[y]!=-1) continue; q.push(y),be[y]=0,dist[y]=dist[x]+1; if(y==t) f=1; } } return f; } int DFS(int x,int sum){ if(x==t||!sum) return sum; int siz=v[x].size(),ans=0; for(int i=0;i<siz;i++){ int y=v[x][i].u,w=v[x][i].w,id=v[x][i].id;be[x]=i; if(!w||dist[x]!=dist[y]-1) continue; int now=DFS(y,min(sum-ans,w)); if(!now) dist[y]=0; v[x][i].w-=now,v[y][id].w+=now,ans+=now; } return ans; } int dinic(){ int ans=0,now=0; while(BFS()) while(now=DFS(s,INF)) ans+=now; return ans; } }T; int n,m,k,tot=0; int qq[4]={3,4,1,2}; int qqq[4]={4,3,2,1}; int fx[5]={0,1,-1,0,0}; int fy[5]={0,0,0,1,-1}; bool Check(int x,int y){ if(x<=0||x>n) return 0; if(y<=0||y>m) return 0; return 1; } struct ss{ int x,y,col,val; }a[1000005]; #define mp make_pair #define pii pair<int,int> map<pii ,int > f; signed main(){ ios_base::sync_with_stdio(false); cin.tie(NULL), std::cout.tie(NULL); cin>>n>>m>>k;T.s=0,T.t=k*2+1; for(int i=1;i<=k;i++){ cin>>a[i].x>>a[i].y>>a[i].val; swap(a[i].x,a[i].y); if(a[i].x&1) a[i].col=qqq[a[i].y%4]; else a[i].col=qq[a[i].y%4]; f[mp(a[i].x,a[i].y)]=i; } for(int i=1;i<=k;i++){ int x=a[i].x,y=a[i].y; T.Add(i,i+k,a[i].val); for(int kk=1;kk<=4;kk++){ int qx=x+fx[kk],qy=y+fy[kk]; if(!Check(qx,qy)||f.find(mp(qx,qy))==f.end()) continue; int id=f[mp(qx,qy)]; if(a[id].col!=a[i].col+1) continue; T.Add(i+k,id,INF); } if(a[i].col==1) T.Add(T.s,i,INF); if(a[i].col==4) T.Add(i+k,T.t,INF); } cout<<T.dinic(); return 0; }