zoukankan      html  css  js  c++  java
  • CTSC 1999 家园 【网络流24题】星际转移

    直接把每一个点,每一天拆成一个点。

    然后每个点到下一天连$inf$的边。

    然后把飞船的路径用容量为飞船容量的边连接。

    然后跑网络流判断是否满流。

    #include <queue>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    #define F(i,j,k) for (int i=j;i<=k;++i)
    #define D(i,j,k) for (int i=j;i>=k;--i)
    #define inf 0x3f3f3f3f
    #define maxn 500005
    
    int n,m,k,p[25],flag=0,S=0,T=maxn-1,ans=0;
    int sta[25][25],num[25];
    int h[maxn],to[maxn],ne[maxn],fl[maxn],fr[maxn],en=0;
    int hash[25][500],cnt=0,dis[maxn];
    queue <int> q;
    
    void add(int a,int b,int c)
    {
    	to[en]=b;fr[en]=a;ne[en]=h[a];fl[en]=c;h[a]=en++;
    	to[en]=a;fr[en]=b;ne[en]=h[b];fl[en]=0;h[b]=en++;
    }
    
    bool tell()
    {
    	memset(dis,-1,sizeof dis);
    	while (!q.empty()) q.pop();
    	dis[S]=0;q.push(S);
    	while (!q.empty())
    	{
    		int x=q.front();q.pop();
    		for (int i=h[x];i>=0;i=ne[i])
    		{
    			if (fl[i]>0&&dis[to[i]]==-1)
    			{
    				dis[to[i]]=dis[x]+1;
    				q.push(to[i]);
    			}
    		}
    	}
    	if (dis[T]==-1) return false;
    	return true;
    }
    
    int zeng(int k,int now)
    {
    	if (k==T) return now;
    	int r=0;
    	for (int i=h[k];i>=0&&now>r;i=ne[i])
    		if (dis[k]+1==dis[to[i]]&&fl[i]>0)
    		{
    			int t=zeng(to[i],min(now-r,fl[i]));
    			fl[i]-=t;fl[i^1]+=t;r+=t;
    		}
    	if (!r) dis[k]=-1;
    	return r;
    }
    
    int main()
    {
    	memset(h,-1,sizeof h);
    	scanf("%d%d%d",&n,&m,&k);
    	F(i,1,m)
    	{
    		scanf("%d",&p[i]);
    		scanf("%d",&num[i]);
    		F(j,0,num[i]-1)
    		{
    			scanf("%d",&sta[i][j]);
    			if (sta[i][j]==-1) sta[i][j]=n+1;
    		}
    	}
    	F(i,0,n+1)
    		F(j,0,205)
    			hash[i][j]=++cnt;
    	add(S,hash[0][0],k);
    	add(hash[n+1][0],T,inf);
    	for (int z=0;z<=200;++z)
    	{
    		int tmp;
    		F(i,0,n+1)
    			add(hash[i][z],hash[i][z+1],inf);
    		F(i,1,m)
    			add(hash[sta[i][z%num[i]]][z],hash[sta[i][(z+1)%num[i]]][z+1],p[i]);
    		add(hash[n+1][z+1],T,inf);
    		while (tell()) while (tmp=zeng(S,inf)) ans+=tmp;
    		if (ans==k)
    		{
    			flag=1;
    			printf("%d
    ",z+1);
    			break; 
    		}
    	}
    	if (!flag) printf("%d
    ",0);
    }
    

      

  • 相关阅读:
    数据库相关(转)
    sql之left join、right join、inner join的区别
    PHP面试编程
    实验6 shell程序设计一(1)
    实验7 shell程序设计二(1)
    Linux软件安装管理
    Linux常用命令总结
    合唱团
    linux课后作业1
    linux网络服务实验
  • 原文地址:https://www.cnblogs.com/SfailSth/p/6743731.html
Copyright © 2011-2022 走看看