hdu 3416 Marriage Match IV

从城市A到B,每次都走最短路,但每条边最多走一次,能够走多少次

曾做过一次这种题。建最短路树,跑SPFA

值得注意的是,如果跑dij的时候不建立永久标号,会导致最短路树出错

spfa要不停的进行松弛操作,同理不能这样建最短路树。看网上代码spfa都是正着反着跑两遍spfa,然后判断dis1[u]+dis2[v]+w==dis[B]是否成立。若成立,则u,v为最短路上的边

把网上的和我的都交了一遍,我的更快*_*

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
const int maxn=1008;
const int maxm=100008;
const int INF=0x7f7f7f7f;
struct shit{
	int v,w;
	bool operator<(const shit &a)	const
	{
		return w>a.w;
	}
};
struct fuck{
	int u,v,cap,next;
}edge[maxm<<2];
vector<shit>	g[maxn];
int dis[maxn];
vector<int>	distree[maxn];
bool vis[maxn];
int head[maxn];
int tol;
void init()
{
	tol=0;
	memset(head,-1,sizeof(head));
}
void addedge(int u,int v,int w)
{
	edge[tol].u=u;
	edge[tol].v=v;
	edge[tol].cap=w;
	edge[tol].next=head[u];
	head[u]=tol++;
	edge[tol].u=v;
	edge[tol].v=u;
	edge[tol].cap=0;
	edge[tol].next=head[v];
	head[v]=tol++;
}
int last;
int dep[maxn],gap[maxn];
void bfs(int sour,int sink)
{
	queue<int>	q;
	int i,u,v;
	memset(dep,-1,sizeof(dep));
	memset(gap,0,sizeof(gap));
	q.push(sink);dep[sink]=0;gap[0]=1;
	while(!q.empty())
	{
		u=q.front();q.pop();
		for(i=head[u];i!=-1;i=edge[i].next)
		{
			v=edge[i].v;
			if(dep[v]==-1&&edge[i].cap==0)
			{
				dep[v]=dep[u]+1;
				q.push(v);
				gap[dep[v]]++;
			}
		}
	}
}
int sap(int sour,int sink,int n)
{
	bfs(sour,sink);
	int max_flow=0,top=0,i,u;
	int S[maxn],cur[maxn];
	for(i=0;i<=n;i++)
		cur[i]=head[i];
	u=sour;
	while(dep[u]<last)
	{
		if(u==sink)
		{
			int temp=INF,inser;
			for(i=0;i<top;i++)
				if(edge[S[i]].cap<temp)
				{
					temp=edge[S[i]].cap;
					inser=i;
				}
			for(i=0;i<top;i++)
			{
				edge[S[i]].cap-=temp;
				edge[S[i]^1].cap+=temp;
			}
			max_flow+=temp;
			top=inser;
			u=edge[S[top]].u;
		}
		if(u!=sink&&gap[dep[u]-1]==0)	break;
		for(i=cur[u];i!=-1;i=edge[i].next)
			if(edge[i].cap>0&&dep[u]==dep[edge[i].v]+1)
				break;
		if(i!=-1)
		{
			cur[u]=i;
			S[top++]=i;
			u=edge[i].v;
		}
		else
		{
			int mi=last;
			for(i=head[u];i!=-1;i=edge[i].next)
				if(edge[i].cap>0&&dep[edge[i].v]<mi)
				{
					mi=dep[edge[i].v];
					cur[u]=i;
				}
			gap[dep[u]]--;
			dep[u]=mi+1;
			gap[dep[u]]++;
			if(u!=sour)	u=edge[S[--top]].u;
		}
	}
	return max_flow;
}
void dfs(int u)
{
	int i,v;
	vis[u]=true;
	last++;
	for(i=0;i<distree[u].size();i++)
	{
		v=distree[u][i];
		addedge(u,v,1);
		if(!vis[v])	dfs(v);
	}
}
int dij(int sour,int sink)
{
	bool done[maxn];
	priority_queue<shit>	q;
	int i,u,v,w;
	shit pp;
	pp.v=sour;pp.w=0;
	q.push(pp);
	memset(dis,INF,sizeof(dis));
	memset(done,false,sizeof(done));
	dis[sour]=0;
	while(!q.empty())
	{
		pp=q.top();q.pop();
		u=pp.v;
		if(done[u])	continue;//永久标号没有wa数发 
		done[u]=true;
		for(i=0;i<g[u].size();i++)
		{
			v=g[u][i].v;w=g[u][i].w;
			if(dis[v]==dis[u]+w)
				distree[v].push_back(u);
			else if(dis[v]>dis[u]+w)
			{
				dis[v]=dis[u]+w;
				pp.v=v;pp.w=dis[v];
				q.push(pp);
				distree[v].clear();
				distree[v].push_back(u);
			}
		}	
	}
	return dis[sink];
}
int main()
{
	int i,j,t,u,v,w,n,m;
	int sour,sink;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d%d",&n,&m);
		shit pp;
		init();
		for(i=1;i<=n;i++)
		{
			g[i].clear();
			distree[i].clear();
		}
		for(i=1;i<=m;i++)
		{
			scanf("%d%d%d",&u,&v,&w);
			pp.v=v;pp.w=w;
			g[u].push_back(pp);//曾建立无向边wa数发 
		}
		scanf("%d%d",&sour,&sink);
		int bitch=dij(sour,sink);
		if(bitch==INF)
		{
			printf("0\n");
			continue;
		}
		memset(vis,false,sizeof(vis));
		last=0;
		dfs(sink);
		bitch=sap(sink,sour,n);
		printf("%d\n",bitch);
	}
	return 0;
}

 

posted on 2015-09-01 21:45  此剑之势愈斩愈烈  阅读(125)  评论(0编辑  收藏  举报

导航