首页 > 代码库 > sgu-212 Data Transmission

sgu-212 Data Transmission

 题目大意:

给你一个图,n(点数),m(边数),l,和每个点上的标号h,h表示到源点的最短路,h=1表示是源点,h=l表示是汇点,显然是一个层次图,然后要你求最大流。


解题思路:

首先我们注意一下数据范围,然后我就怂了,本来看到题目觉得就是分分钟dinic上去秒掉的,但是我还是too naive,所以我只能滚粗去学预流推进了。。。。。。。

由于预流推进很难讲,所以请大家自己去查阅资料吧。

我们假设大家都会了预流推进,但是我自己写的最高标号预流推进居然超时了,然后我就各种丧心病狂的优化,我来介绍一点优化吧!

优化1:输出优化,把所有要输出的都转成字符串,然后用putchar或者puts

优化2:我们不需要进行BFS或着DFS,只需要用输入的h就行了

优化3:听说sgu开了O2对吧,inline函数搞起!!

优化4:我们应该尽量开小空间,因为空间小速度快啊!!!

优化5:用hash表示这个数是否在优先队列中,以免重复进队!!


AC代码:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <queue>
#define MAX(a,b) ((a)>(b)?(a):(b))
#define MIN(a,b) ((a)>(b)?(b):(a))

using namespace std;

short h[1510]={0};
struct list
{
	int x;
	int H;
	bool friend operator < (const list &a,const list &b)
	{
		return a.H<b.H;
	}
};

struct bian_
{
	short num;
	int next;
}b[600010]={{0,0}};

int First[1510]={0};

int n,m,l;
int s,t;
priority_queue <list> dui;
int flow[1510][1510]={{0}};
int yl[1510]={0};
short bian[300010][2]={{0}};
int ss=0;
bool hash[1510]={0};
char ans[100000]="\0";
int ansp;

inline void Add(int i,int j,int k)
{
	b[k].num=j;
	b[k].next=First[i];
	First[i]=k;
	return;
}

inline void get_ch(int k)
{
	char help[10]="\0";
	int i;
	if(k==0)
		ans[++ansp]='0';
	else
	{
		for(i=0;k!=0;k/=10)
			help[++i]=k%10+'0';
		for(;i>0;--i)
			ans[++ansp]=help[i];
	}
	ans[++ansp]='\n';
	return;
}

int main()
{
	scanf("%d%d%d",&n,&m,&l);
	for(register int i=1;i<=n;++i)
	{
		scanf("%d",&h[i]);
		if(h[i]==1)
			s=i;
		if(h[i]==l)
			t=i;
		h[i]=l+1-h[i];
	}
	for(register int i=1;i<=m;++i)
	{
		scanf("%d%d",&bian[i][0],&bian[i][1]);
		scanf("%d",&flow[bian[i][0]][bian[i][1]]);
		Add(bian[i][0],bian[i][1],i*2-1);
		Add(bian[i][1],bian[i][0],i*2);
	}
	
	h[s]=l+1;
	yl[s]=2e9;
	yl[t]=-2e9;
	struct list q;
	q.x=s;
	q.H=h[s];
	dui.push(q);
	hash[s]=1;
	++ss;
	
	for(;ss!=0;)
	{
		q=dui.top();
		dui.pop();
		--ss;
		int u=q.x;
		hash[u]=0;
		for(register int i=First[u];i!=0;i=b[i].next)
		{
			int v=b[i].num;
			if(yl[u]==0) break;
			int p=MIN(flow[u][v],yl[u]);
			if(p>0 && (u==s || h[u]==h[v]+1))
			{
				flow[u][v]-=p;
				flow[v][u]+=p;
				yl[u]-=p;
				yl[v]+=p;
				if(v!=s && v!=t && hash[v]==0)
				{
					q.x=v;
					q.H=h[v];
					dui.push(q);
					++ss;
					hash[v]=1;
				}
			}
		}
		if(u!=s && u!=t && yl[u]>0)
		{
			++h[u];
			q.x=u;
			q.H=h[u];
			dui.push(q);
			++ss;
			hash[u]=1;
		}
	}
	for(register int i=1;i<=m;++i)
		get_ch(flow[bian[i][1]][bian[i][0]]);
	for(register int i=1;i<=ansp;++i)
		putchar(ans[i]);
	return 0;
}


sgu-212 Data Transmission