瀋陽預選賽的1011,剛開始沒想到用bfs找最短路,還找了一個能找出所有多條最短路徑的板子,結果一直猶豫最短路+網絡流會不會超時,到了也沒寫完這題。
Input
For each test case, in the first line there are two integers N(N \leq 1000) and M(M \leq 10000).
The i-the line of the next M lines describes the i-th edge with three integers u,v and w where 0 \leq w \leq 1000 denoting an edge betweenu and v of barricade cost w.
Output
Sample Input
1 4 4 1 2 1 2 4 2 3 1 3 4 3 4
Sample Output
4
題解:這裏因爲它所有路徑的長度都爲1,所以不需要什麼算法去實現找多條最短路,只需要用bfs給點標號,由bfs的最優解特性可知,它找到的一定是最短路上的點,當搜完一遍後,用深搜再搜一遍,將所有滿足dis[v]=dis[u]+1,的點建圖形成一個新的網絡,這樣我們就可以在新網絡上裸最大流了,由於他要求用最少的木頭去建造障礙物,實際上就是求這張網絡帶源點的點集和帶匯點的點集之間的最小割,也就是最大流,這樣就是裸模板了。
代碼:
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iostream>
#include <cmath>
#include <vector>
#include <queue>
#define MEMINF(a) memset(a,0x3f,sizeof a)
#define MEM(a,b) memset(a,b,sizeof a)
using namespace std;
typedef long long LL;
const int MAXN=1e5+10;
const int MAXM=4e5+10;
const int INF=0x3f3f3f3f;
struct MaxFlow{
int head[MAXN];
struct Edge{
int u,v,nex,cap,flow;
}edge[MAXM];
int tot,s,t,n,m;
int dis[MAXN];
int cur[MAXN];
void Dinic_init(int n,int m){
this->s=n;
this->t=1;
this->n=n;
this->m=m;
MEM(head,-1);
tot=0;
}
void Addedge(int u,int v,int w) {
edge[tot].v=v,edge[tot].cap=w,edge[tot].flow=0,edge[tot].nex=head[u],head[u]=tot++;
edge[tot].v=u,edge[tot].cap=0,edge[tot].flow=0,edge[tot].nex=head[v],head[v]=tot++;
}
bool bfs() {
MEM(dis,-1);
queue<int>q;
dis[s]=0;
q.push(s);
while (!q.empty()) {
int u=q.front();
q.pop();
for (int i=head[u]; ~i; i=edge[i].nex) {
int v=edge[i].v;
if (edge[i].cap>edge[i].flow&&dis[v]==-1) {
q.push(v);
dis[v]=dis[u]+1;
}
}
}
return dis[t]!=-1;
}
int dfs(int u,int delta) {
if (u==t||delta==0)
return delta;
int ret=0;
int aug;
for(int &i=cur[u]; ~i; i=edge[i].nex) {
int v=edge[i].v;
if (dis[v]==dis[u]+1&&(aug=dfs(v,min(edge[i].cap-edge[i].flow,delta)))>0) {
edge[i].flow+=aug;
edge[i^1].flow-=aug;
delta-=aug;
ret+=aug;
if (delta==0) break;
}
}
return ret;
}
void dinic() {
int ret=0;
while(bfs()) {
memcpy(cur,head,sizeof head);
ret+=dfs(s,INF);
//cout<<ret<<endl;
}
cout<<ret<<endl;
}
}nima;
struct Search_{
int head[MAXN];
int level[MAXN];
int tot;
int s;
int vis[MAXN];
struct Edge {
int u,v,w;
int nex;
}edge[MAXM];
void Addedge(int u,int v,int w) {
edge[tot].v=v;edge[tot].u=u;edge[tot].w=w;edge[tot].nex=head[u],head[u]=tot++;
edge[tot].v=u;edge[tot].u=v;edge[tot].w=w;edge[tot].nex=head[v],head[v]=tot++;
}
void search_init(int n) {
MEM(level,-1);
tot=0;
MEM(head,-1);
MEM(vis,0);
this->s=n;
}
void bfs() {
queue<int>q;
level[s]=0;
q.push(s);
while (!q.empty()) {
int u=q.front();
q.pop();
for (int i=head[u]; ~i; i=edge[i].nex) {
int v=edge[i].v;
if (level[v]==-1) {
level[v]=level[u]+1;
q.push(v);
}
}
}
}
void dfs(int u) {
vis[u]=1;
for (int i=head[u]; ~i; i=edge[i].nex) {
int v=edge[i].v;
if (level[v]==level[u]+1) {
//printf("u:%d v:%d w:%d\n",u,v,edge[i].w);
nima.Addedge(u,v,edge[i].w);
if (!vis[v])
dfs(v);
}
}
}
void search_work() {
bfs();
dfs(s);
return;
}
}cao;
int main(){
int n,m;
int Test;
cin>>Test;
while (Test--){
scanf("%d %d",&n,&m);
int u,v,w;
cao.search_init(n);
nima.Dinic_init(n,m);
for (int i=0; i<m; ++i) {
scanf("%d %d %d",&u,&v,&w);
cao.Addedge(u,v,w);
}
cao.search_work();
nima.dinic();
}
}