BZOJ1001 [Beijing2006] 狼抓兔子
相關資料:
根據最大流-最小割定理,一個網路中,兩個邊緣點之間的最大流等於最小割(最小割就是用一條割線將兩個點分割在兩個圖中,令刪去的邊的總權值最小。因此我們可以建圖,將每個圖(在本題中是每個三角形)作為一個點,點與點之間的連線就等於它們穿過的那條線的權值。在起點和終點間連一條線,線的內部和外部分別建立兩個點,將這兩個點和相鄰的三角形連線,然後刪去這條邊在整個圖中求最短路即可。
程式碼: (ps:當時也是在學習的過程中,所以借鑑了別人的程式碼)
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
using namespace std;
const int N=2000006, INF=0x3fffffff, E=N*3;
struct ARC {
int u, val, next;
inline void init(int a, int b, int c) {
u=a, val=b, next=c;
}
} arc[E];
int head[N], tot, S, T, n, m, dis[N];
bool vs[N];
inline void add_arc(int s, int t, int val) {
arc[tot].init(t, val, head[s]);
head[s]=tot++;
}
void SPFA(){
queue<int> q;
fill(dis, dis+T+1, INF);
fill(vs, vs+T+1, 0);
q.push(S);
dis[S]=S,vs[S]=true;
while (!q.empty()){
int c=q.front(),i;
q.pop();vs[c]=false;
for (i=head[c]; i!=-1; i=arc[i].next){
if (dis[c]+arc[i].val<dis[arc[i].u]){
dis[arc[i].u]=dis[c]+arc[i].val;
if (!vs[arc[i].u]){
q.push(arc[i].u);
vs[arc[i].u]=true;
}
}
}
}
printf("%d",dis[T]);
}
void read(int &x) {
char c;
while((c=getchar())<'0' || c>'9');
x=c-'0';
while((c=getchar())>='0' && c<='9') x=(x<<3)+(x<<1)+c-'0';
}
void Input() {//讀入
for(int i=0, id1, id2, a; i<=n-1; i++)//讀入相鄰橫邊
for(int j=1; j<=m-1; j++) {
read(a);
id1=((i-1)*(m-1)+j)*2-1;
id2=(i*(m-1)+j)*2;//從1圖通往2圖
if(i==0) id1=T,add_arc(id2, id1, a);
else if(i==n-1) id2=S,add_arc(id2, id1, a);
else add_arc(id1, id2, a),add_arc(id2, id1, a);
}//增邊
for(int i=1, id1, id2, a; i<=n-1; i++)
for(int j=0; j<m; j++) {
read(a);
id1=((i-1)*(m-1)+j)*2;
id2=((i-1)*(m-1)+j+1)*2-1;
if(j==0) id1=S,add_arc(id1, id2, a);
else if(j==m-1) id2=T,add_arc(id1, id2, a);
else add_arc(id1, id2, a),add_arc(id2, id1, a);
}
for(int i=1, id1, id2, a; i<=n-1; i++)
for(int j=1; j<=m-1; j++) {
read(a);
id1=((i-1)*(m-1)+j)*2;
id2=((i-1)*(m-1)+j)*2-1;
add_arc(id1, id2, a);
add_arc(id2, id1, a);
}
}
int main() {
freopen("1001.in","r",stdin);
freopen("1001.out","w",stdout);
read(n), read(m);//讀入整數
S=0, T=(n-1)*(m-1)*2+1;//S是源點T是匯點
fill(head, head+T+1, -1), tot=0;//初始化為全-1
if(n==1 || m==1) {//處理特殊情況
if(n>m) swap(n, m);
int ans=INF;
for(int i=1, a; i<m; i++) {
read(a);
if(ans>a) ans=a;
}
printf("%d\n", ans==INF?0:ans);
}
else Input(), SPFA();
return 0;
}
//BZOJ 1001
ps誰告訴我為什麼程式碼片點確定沒反應qwqwq