1. 程式人生 > >BZOJ3511 土地劃分 題解&程式碼

BZOJ3511 土地劃分 題解&程式碼

pkusc發現自己不會費用流233333於是兩天速成費用流【然而這是一道最小割(最大流QwQ
題意:
給出n個點m條邊,並設定:
點x在被劃分至集合A時獲得權值A[x],否則即被劃分至集合B並獲得權值B[x];
邊(x,y)連線的x和y均屬於集合A時獲得權值ea,均屬於集合B時獲得權值eb,否則獲得權值-ec。

題解:這題…反正我是沒自己建出圖來。
對於點x,從S(代表集合A)向x連容量為va的邊,從x向T(代表集合B)連容量為vb的邊。
對於邊(x,y),從S向x和y分別連容量為ea/2的邊,從x和y向T分別連容量為eb/2的邊,然後x和y中間互相連兩條容量為ea/2+eb/2+ec的邊。

這樣的話,圖中最大流就是劃分這個圖的最小花費。
於是答案就是權值和減去最小割(最大流)
反正換我肯定做不出來orz還是智商受到了限制

/**************************************************************
    Problem: 3511
    User: Rainbow6174
    Language: C++
    Result: Accepted
    Time:1612 ms
    Memory:6744 kb
**************************************************
**************/ #include <cstdio> #include<iostream> #include <algorithm> #define LL long long using namespace std; const int maxn = 10005; const int maxm = 40005; const int maxq = 50005; const int inf = 0x3f3f3f3f; int n,m,v,head[maxn],cur[maxn],cnt,st,ed,deep[maxn],q[maxq]; LL ans; struct edge{ int
v,w,next; } e[4*maxn+10*maxm]; void add(int u, int v, int w,int rw) { e[cnt]=(edge){v,w,head[u]}; head[u]=cnt++; e[cnt]=(edge){u,rw,head[v]}; head[v]=cnt++; } bool bfs(void) { for(int i=st; i<=ed; i++) deep[i]=-1; int h=0,t=0; deep[st]=1; q[t++]=st; while(h != t) { int u = q[h++]; for(int i=head[u]; i!=-1; i=e[i].next) if(e[i].w && deep[e[i].v]==-1) { deep[e[i].v]=deep[u]+1; if(e[i].v==ed) return true; q[t++]=e[i].v; } } return false; } int dfs(int x,int flow) { if(x==ed)return flow; int left=flow; for(int i=cur[x]; i!=-1; i=e[i].next) if(e[i].w && deep[e[i].v]==deep[x]+1) { int tmp=dfs(e[i].v,min(left,e[i].w)); left-=tmp; e[i].w-=tmp; e[i^1].w+=tmp; if(e[i].w)cur[x]=i; if(!left)return flow; } if(left==flow)deep[x]=-1; return flow-left; } LL dinic(void) { LL ret=0; while(bfs()) { for(int i=st; i<=ed; i++) cur[i]=head[i]; ret+=(LL)dfs(st,inf); } return ret; } int main(void) { scanf("%d%d",&n,&m); st=0;ed=n+1; for(int i=st; i<=ed; i++) head[i]=-1; add(st,1,inf,0); add(n,ed,inf,0); for(int i=2; i<n; i++) { scanf("%d",&v);v*=2; add(st,i,v,0); ans+=v; } for(int i=2; i<n; i++) { scanf("%d",&v);v*=2; add(i,ed,v,0); ans+=v; } for(int i=1; i<=m; i++) { int x,y,ea,eb,ec; scanf("%d%d",&x,&y); scanf("%d%d%d",&ea,&eb,&ec); add(st,x,ea,0); add(st,y,ea,0); add(x,ed,eb,0); add(y,ed,eb,0); add(x,y,ea+eb+ec*2,ea+eb+ec*2); ans+=(ea+eb)*2; } ans-=dinic(); printf("%lld\n",ans/2); return 0; }

相關推薦

BZOJ3511 土地劃分 題解&程式碼

pkusc發現自己不會費用流233333於是兩天速成費用流【然而這是一道最小割(最大流QwQ 題意: 給出n個點m條邊,並設定: 點x在被劃分至集合A時獲得權值A[x],否則即被劃分至集合B並獲得權值B[x]; 邊(x,y)連線的x和y均屬於集合A時獲得

BZOJ3511: 土地劃分(最小割)

中一 設計 -s 擔心 32位 style font led %d Description Y國有N座城市,並且有M條雙向公路將這些城市連接起來,並且任意兩個城市至少有一條路徑可以互達。 Y國的國王去世之後,他的兩個兒子A和B都想成為新的國王,但他們都想讓這個國家更加

BZOJ3511 土地劃分

一眼最小割 考慮劃為S集代表A國,劃為T集代表B國 建圖:S連每個點流量VA,每個點連T流量VB 對於每條邊,兩個端點點之間連雙向邊流量EC 新建一個點X,S連X流量EA,X連兩個端點流量INF 再新建一個點Y,兩個端點連Y流量INF,Y連T流量EB 認為1號點VA=INF

BZOJ3511土地劃分【最小割】

看了題解才會建圖... 對於點x,從S向x連容量為va的邊,從x向T連容量為vb的邊。 對於邊(u, v),從S向u和v分別連兩條容量為ea / 2的邊,從u和v向T分別連兩條容量為eb / 2的邊,然後u和v中間互相連兩條容量為ea / 2 + eb / 2 + ec的

P1025 數的劃分 題解

這題其實是排列組合裡的題,可以把一個數值為n的數當做n個小球,劃分的份數k當做k個盒子,那麼本題可以轉化為“將n個小球放到k個盒子中,小球之間與盒子之間沒有區別,並且最後的結果不允許空盒” 將n個小球放到k個盒子中的情況總數 = a.至少有一個盒子只有一個小球的情況數 +b.沒有一個盒子

【POJ2406】Power Strings 中文題意&題解&程式碼(C++)

Power Strings Time Limit: 3000MS Memory Limit: 65536K Description Given two strings a and b we define a*b to be their conca

HDU 1698 Just a Hook 題解&程式碼

題目要求是對於一個初始值均為1的區間進行區間修改,修改目標為:[a,b]區間內的值被修改為c 對於多組資料的每組資料輸出q次修改後的全區間和 基本線段樹了…只有兩個元素需要維護:sum和add,su

POJ3630 Phone List 題解&程式碼

第一次用vim寫程式碼…感覺爽爽噠,終於明白很多程式碼為什麼會有詭異的空格什麼的…習慣 vim的快捷操作幾乎全部是和單詞相關,也就是說如果一句程式碼中間沒有空格…vim的優勢就完全消失了 在下的習慣一時半會改不過來…嘛,不過既然看到了其道理自然是要努力改的

【POJ 3630】Phone List 中文題意&題解&程式碼(C++)

Phone List Time Limit: 1000MS Memory Limit: 65536K Description Given a list of phone numbers, determine if it is consistent

【poj 2488】A Knight's Journey 中文題意&題解&程式碼(C++)

中文題意: 給出一個p行q列的國際棋盤,馬可以從任意一個格子開始走,問馬能否不重複的走完所有的棋盤。如果可以,輸出按字典序排列最小的路徑。列印路徑時,列用大寫字母表示(A表示第一列),行用阿拉伯數

BZOJ1711 [Usaco2007 Open]Dining吃飯 題解&程式碼

題意: 有N頭牛,F種食物和D種飲料,每頭牛有多種喜歡的食物和飲料,每頭牛隻可以吃一種食物和飲料,且每種食物和飲料都只能被一頭牛吃掉。一頭牛滿意當且僅當它吃到滿意的食物並且喝到想喝的飲料,問最多可能讓多少頭牛滿意。 題解: 把每頭牛拆成兩個點x和x+n,給

fzu 1015 土地劃分

#include<iostream> using namespace std; #include<cstdio> struct point { int x,y; }; struct segment { point a,b; }; segment s

導彈防禦塔(題解+程式碼

Description Freda的城堡—— “Freda,城堡外發現了一些入侵者!” “喵…剛剛探究完了城堡建設的方案數,我要歇一會兒嘛lala~” “可是入侵者已經接近城堡了呀!” “別擔心,rainbow,你看呢,這是我剛設計的導彈防禦系統的說~

BZOJ4034 [HAOI2015]T2 題解&程式碼

題意: 有一棵有N個節點的樹,以節點1為根,且點上有權。 有M個操作,分為三種: 操作 1 把節點x的點權增加 a 操作 2 把以節點x為根的樹中所有點的點權都增加a 操作 3 求節點x到根的路徑中所有點的點權和 分析: 操作1和操作2本質上是沒有區

FZU 1015 土地劃分

解題思路:就是求 n 條線段能將矩形劃分成多少個區域。           首先分析直線劃分區域的情況,根據已知的結論:平面上 n 條直線最多可以將平面分成 f ( n ) 個區域,  其中 f ( n )  =  ( n * n + n + 2 ) / 2。    

第一講,整數劃分 JAVA 程式碼(分治實現之一)

整數劃分問題相信很多人都做過,題意是這樣的: 將正整數n表示成一系列正整數之和, n=n1+n2+,,,,,+nk(其中n1>=n2>=......>=nk>=1,k>1) 例如:正整數6有如下11種不同的劃分, 6=1+1+1+1+

【poj 3126】Prime Path 題意&題解&程式碼(C++)

變換的過程要保證 每次變換出來的數都是一個 四位素數,而且當前這步的變換所得的素數 與 前一步得到的素數 只能有一個位不同,而且每步得到的素數都不能重複。 求從a到b最少需要的變換次數。無

【poj 2627】 Sudoku 題意&題解&程式碼(C++)

題目連結: http://poj.org/problem?id=2676 題意: 給出一個未填的數獨,求這個數獨的解並輸出填好的數獨,若此數獨無解,則輸出原給定的錯誤數獨。 題解: dfs回溯

NOI 2015 荷馬史詩 題解&程式碼

對於一些不同的單詞,每個單詞會給出一個出現頻率 對於每個單詞,給它一個唯一的字串型的編號【不是其它字串型編號的字首】 其實是個貪心【噗】,按照哈弗曼樹的形式將出現頻率與編碼長度反序排列…就好了 #

【poj 1159】Palindrome 題意&題解&程式碼(C++)

題目連結: http://poj.org/problem?id=1159 題意: 給出一個長為n的字串,求最少新增幾個字元可以將這個字串變為迴文字串。 題解: 要把這個串變為迴文串,很容易想到