您的位置:首页 > 其它

HDU 5889 Barricade 2016 ACM/ICPC Asia Regional Qingdao Online 1011

2016-09-17 18:59 363 查看
把最短路那个图拿出来 再跑最小割就可以了。

……这题和我bin神最大流分类的第一题极其相识,只是一个是有向图一个是无向图点击打开链接

对最短路的图也是这样想的:

先用dijkstra求出1-N的最短路,可以记录每个节点的前一个节点,然后从N 往前推,比如到b 节点时,已经知道 到b 的最短路是dis[b], 那么跟b 所有相连的变中,如果dis[b] = dis[a] + dis(a, b) 那么 新图中 a 到b 就可以连一条边。

但bin神模版里这些都有,方法和这个有点不一样但也类似。直接改两下就能交了过……

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
const int MAXN=1010;
const int MAXM=20010;
const int INF=0x3f3f3f3f;

//×î´óÁ÷SAP

struct Node
{
int to,next,cap;
}edge[MAXM];
int tol;
int head[MAXN];
int gap[MAXN],dis[MAXN],pre[MAXN],cur[MAXN];
void init()
{
tol=0;
memset(head,-1,sizeof(head));
}
void addedge(int u,int v,int w,int rw=0)
{
edge[tol].to=v;edge[tol].cap=w;edge[tol].next=head[u];head[u]=tol++;
edge[tol].to=u;edge[tol].cap=rw;edge[tol].next=head[v];head[v]=tol++;
}

int sap(int start,int End,int nodenum)
{
memset(dis,0,sizeof(dis));
memset(gap,0,sizeof(gap));
memcpy(cur,head,sizeof(head));
int u=pre[start]=start,maxflow=0,aug=-1;
gap[0]=nodenum;
while(dis[start]<nodenum)
{
loop:
for(int &i=cur[u];i!=-1;i=edge[i].next)
{
int v=edge[i].to;
if(edge[i].cap&&dis[u]==dis[v]+1)
{
if(aug==-1||aug>edge[i].cap)
aug=edge[i].cap;
pre[v]=u;
u=v;
if(v==End)
{
maxflow+=aug;
for(u=pre[u];v!=start;v=u,u=pre[u])
{
edge[cur[u]].cap-=aug;
edge[cur[u]^1].cap+=aug;
}
aug=-1;
}
goto loop;
}
}
int mindis=nodenum;
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].to;
if(edge[i].cap&&mindis>dis[v])
{
cur[u]=i;
mindis=dis[v];
}
}
if((--gap[dis[u]])==0)break;
gap[dis[u]=mindis+1]++;
u=pre[u];
}
return maxflow;
}

//SPFA
int first[MAXN];
bool vis[MAXN];
int cnt[MAXN];
int que[MAXN];
int dist[MAXN];
struct Edge
{
int to,v,next;
}edge1[MAXM];
int tt;
void add(int a,int b,int v)
{
edge1[tt].to=b;
edge1[tt].v=v;
edge1[tt].next=first[a];
first[a]=tt++;
}
bool SPFA(int start,int n)
{
int Front=0,rear=0;
for(int v=1;v<=n;v++)
{
if(v==start)
{
que[rear++]=v;
vis[v]=true;
cnt[v]=1;
dist[v]=0;
}
else
{
vis[v]=false;
cnt[v]=0;
dist[v]=INF;
}
}
while(Front!=rear)
{
int u=que[Front++];
vis[u]=false;
if(Front>=MAXN)Front=0;
for(int i=first[u];i!=-1;i=edge1[i].next)
{
int v=edge1[i].to;
if(dist[v]>dist[u]+edge1[i].v)
{
dist[v]=dist[u]+edge1[i].v;
if(!vis[v])
{
vis[v]=true;
que[rear++]=v;
if(rear>=MAXN)rear=0;
if(++cnt[v]>n)return false;
}
}
}
}
return true;
}
int a[10100],b[10010],c[10010];
int dist1[MAXN],dist2[MAXN];
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int T;
int n,m;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
int A=1,B=n;
for(int i=0;i<m;i++)
scanf("%d%d%d",&a[i],&b[i],&c[i]);
tt=0;
memset(first,-1,sizeof(first));
for(int i=0;i<m;i++){
add(a[i],b[i],1);
add(b[i],a[i],1);
}
SPFA(A,n);

memcpy(dist1,dist,sizeof(dist));
tt=0;
memset(first,-1,sizeof(first));
for(int i=0;i<m;i++){
add(b[i],a[i],1);
add(a[i],b[i],1);
}
SPFA(B,n);
memcpy(dist2,dist,sizeof(dist));
init();
for(int i=0;i<m;i++)
{
if(a[i]!=b[i] && (dist1[a[i]]+dist2[b[i]] + 1==dist1[B]))
{
addedge(a[i],b[i],c[i]);
}
else if(a[i]!=b[i] && dist2[a[i]]+dist1[b[i]] + 1==dist2[A])
{
addedge(b[i],a[i],c[i]);
}

}
printf("%d\n",sap(A,B,n));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐