您的位置:首页 > 其它

Marriage Match IV HDU - 3416

2017-12-02 09:17 176 查看
点击打开链接

这个题也是看了题解才想到要用最短路和网络流结合的。。

题目要求每次只能走最短路 意思不是走一次最短路就把这条路径删除 然后再找新的最短路即原图的次短路  而是仍然找一条和最开始的最短路长度一样的路径

这样所有构成最短路的边都是可以确定的

反向建图 dis1
代表从起点ss到每个点的最短距离 dis2
代表从终点ee到每个点的最短距离 对于一条边edge[i] 如果dis1[edge[i].u]+edge[i].w+dis2[edge[i].v]==dis1[ee] 则这条边就在一条最短路上

最后 把起点作源点 终点作汇点 以所有最短路上的边建立网络流模型(边权值为1) 就可以知道 利用所有的这些边可以凑数几条从源点到汇点的增广路

因为边权值是1 所以每条增广路的流量都是1 最终得到的最大流即是增广路条数

#include <stdio.h>
#include <queue>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 0x3f3f3f3f

struct nodeI
{
int u;
int v;
int w;
};

struct nodeII
{
int v;
int w;
int next;
};

struct nodeIII
{
friend bool operator < (nodeIII n1,nodeIII n2)
{
return n1.w>n2.w;
}
int v;
int w;
};

priority_queue <nodeIII> que;
nodeI gg[100010];
nodeII edge1[100010],edge2[100010],edge3[200010];
int first1[1010],first2[1010],first3[1010],dis1[1010],dis2[1010],book[1010];
int dis[1010],gap[1010],cur[1010],pre[1010];
int n,m,num,ss,ee,ans;

void addedge(int u,int v,int w,nodeII* edge,int* first)
{
edge[num].v=v;
edge[num].w=w;
edge[num].next=first[u];
first[u]=num++;
return;
}

void calculate(nodeII* edge,int* first,int* dis,int &s)
{
nodeIII cur,tem;
int i,u,v,w;
while(!que.empty()) que.pop();
for(i=1;i<=n;i++)
{
dis[i]=N;
book[i]=0;
}
tem.v=s,tem.w=0;
que.push(tem);
dis[s]=0;
while(!que.empty())
{
cur=que.top();
que.pop();
u=cur.v;
if(book[u]==1) continue;
book[u]=1;
for(i=first[u];i!=-1;i=edge[i].next)
{
v=edge[i].v,w=edge[i].w;
if(book[v]==0&&dis[v]>dis[u]+w)
{
dis[v]=dis[u]+w;
tem.v=v,tem.w=dis[v];
que.push(tem);
}
}
}
return;
}

void judge()
{
int i,u,v,w;
memset(first3,-1,sizeof(first3));
num=0;
for(i=1;i<=m;i++)
{
u=gg[i].u,v=gg[i].v,w=gg[i].w;
if(dis1[u]+w+dis2[v]==dis1[ee])
{
addedge(u,v,1,edge3,first3);
addedge(v,u,0,edge3,first3);
}
}
return;
}

void bfs()
{
queue <int> que;
int i,u,v;
memset(dis,-1,sizeof(dis));
memset(gap,0,sizeof(gap));
que.push(ee);
dis[ee]=0;
while(!que.empty())
{
u=que.front();
que.pop();
gap[dis[u]]++;
for(i=first3[u];i!=-1;i=edge3[i].next)
{
v=edge3[i].v;
if(dis[v]==-1)
{
que.push(v);
dis[v]=dis[u]+1;
}
}
}
return;
}

void isap()
{
int j,u,v,w,flow,minn;
bfs();
memcpy(cur,first3,sizeof(first3));
memset(pre,-1,sizeof(pre));
ans=0,u=ss,flow=N;
while(dis[ss]<n)
{
int &i=cur[u];
for(;i!=-1;i=edge3[i].next)
{
v=edge3[i].v,w=edge3[i].w;
if(dis[v]+1==dis[u]&&w>0)
{
pre[v]=i;
u=v,flow=min(flow,w);
if(u==ee)
{
while(u!=ss)
{
j=pre[u];
edge3[j].w-=flow;
edge3[j^1].w+=flow;
u=edge3[j^1].v;
}
ans+=flow,flow=N;
}
break;
}
}
if(i==-1)
{
if(--gap[dis[u]]==0) break;
cur[u]=first3[u];
minn=n-1;
for(j=first3[u];j!=-1;j=edge3[j].next)
{
v=edge3[j].v,w=edge3[j].w;
if(w>0)
{
minn=min(minn,dis[v]);
}
}
dis[u]=minn+1;
gap[dis[u]]++;
if(u!=ss)
{
u=edge3[pre[u]^1].v;
}
}
}
return;
}

int main()
{
int t,i;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
for(i=1;i<=m;i++)
{
scanf("%d%d%d",&gg[i].u,&gg[i].v,&gg[i].w);
}
scanf("%d%d",&ss,&ee);

memset(first1,-1,sizeof(first1));
num=0;
for(i=1;i<=m;i++)
{
addedge(gg[i].u,gg[i].v,gg[i].w,edge1,first1);
}
calculate(edge1,first1,dis1,ss);

memset(first2,-1,sizeof(first2));
num=0;
for(i=1;i<=m;i++)
{
addedge(gg[i].v,gg[i].u,gg[i].w,edge2,first2);
}
calculate(edge2,first2,dis2,ee);

judge();

isap();

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