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的字串,求最少新增幾個字元可以將這個字串變為迴文字串。 題解: 要把這個串變為迴文串,很容易想到