zoukankan      html  css  js  c++  java
  • Luogu P2754 【[CTSC1999]家园 / 星际转移问题】

    Description

    传送门


    Solution

    判断有无解可以使用并查集,如果最后地球和月球能处在同一个集合中,那么肯定可以到达,只是时间长短的问题。

    因为多个飞船是同时飞行的,这样的问题不好直接处理。考虑星球的个数特别少,这时可以考虑按照时间轴建立分层图,(S)向每个时间点的地球连容量为(INF)的有向边,每个星球向下个时间点的同一个星球连容量为(INF)的有向边,表示这个星球的人等待到了下个时间点;每个飞船所在星球向飞船下个时间点到达的星球连容量为承载人的数量的有向边,表示可以进行飞行转移。

    然后枚举时间,如果某个时间点最大流的比(k)大就输出时间,每次直接在残余网络上进行增广即可。


    Code

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <queue>
    using namespace std;
    
    const int N = 50050;	
    const int M = 100050;
    const int INF = 999999999;
    
    int n, m, s, t, head[N], num = 1, vis[N], d[N], mincost, maxflow, cur[N], k, a[5550][5550], fa[N], tim, b[500];
    
    struct Node
    {
    	int next, to, flow;
    } edge[M * 2];
    
    void Addedge(int u, int v, int w)
    {
    	edge[++num] = (Node){head[u], v, w};
    	head[u] = num;
    }
    
    void Add(int u, int v, int w)
    {
    //	cout << u << " " << v << endl;
    	Addedge(u, v, w);
    	Addedge(v, u, 0);
    	return;
    }
    
    template <class T>
    void Read(T &x)
    {
    	x = 0; int p = 0; char st = getchar();
    	while (st < '0' || st > '9') p = (st == '-'), st = getchar();
    	while (st >= '0' && st <= '9') x = (x << 1) + (x << 3) + st - '0', st = getchar();
    	x = p ? -x : x;
    	return;
    }
    
    template <class T>
    void Put(T x)
    {
    	if (x < 0) putchar('-'), x = -x;
    	if (x > 9) Put(x / 10);
    	putchar(x % 10 + '0');
    	return;
    }
    
    int Find(int x) { return fa[x] == x ? fa[x] : Find(fa[x]); }
    
    void Merge(int a, int b)
    {
    	int pa = Find(a), pb = Find(b);
    	if (pa == pb) return;
    	else fa[pa] = pb;	
    } 
    
    bool Bfs()
    {
        queue<int> q;
        for (int i = 0; i <= t; i++) d[i] = 0;
        d[s] = 1; q.push(s);
        while (!q.empty())
        {
            int u = q.front(); q.pop();
            for (int i = head[u]; i; i = edge[i].next)
                if (!d[edge[i].to] && edge[i].flow)
                {
                    d[edge[i].to] = d[u] + 1;
                    q.push(edge[i].to);
                    if (edge[i].to == t) return 1;
                }
        }
        return 0;
    }
    
    int Dinic(int x, int flow)
    {
        if (x == t || !flow) return flow;
        int rest = flow;
        for (int i = head[x]; i && rest; i = edge[i].next)
            if (edge[i].flow && d[edge[i].to] == d[x] + 1)
            {
                int v = edge[i].to;
                int tmp = Dinic(v, min(rest, edge[i].flow));
                rest -= tmp;
                edge[i].flow -= tmp;
                edge[i ^ 1].flow += tmp;
                if (!tmp) d[v] = 0;
            }
        return flow - rest;
    }
    
    int Maxflow()
    {
    	int maxflow = 0, tmp;
    	while (Bfs())
    	{
    		tmp = Dinic(s, INF);
    		if (tmp) maxflow += tmp;
    	}
    	return maxflow;
    }
    
    void Solve()
    {
    	while(Bfs())
    	{
    		for (int i = 0; i <= t; i++) cur[i] = head[i];
    		maxflow += Dinic(s, INF);
    	}
    	return; 
    }
    
    int Id(int a, int b)
    {
    	if (b == t) return t;
    	return (n + 1) * a + b;
    }
    
    int main()
    {
    	Read(n); Read(m); Read(k);
    	t = 50000;
    	for (int i = 1; i <= t; i++) fa[i] = i;
    	for (int i = 1; i <= m; i++)
    	{
    		Read(b[i]); Read(a[i][0]);
    		for (int j = 1; j <= a[i][0]; j++) 
    		{
    			Read(a[i][j]);
    			if (a[i][j] == 0) a[i][j] = n + 1;
    			if (a[i][j] == -1) a[i][j] = t;
    			if (j > 1) Merge(a[i][j], a[i][j - 1]);
    		}
    		Merge(a[i][1], a[i][a[i][0]]);
    	}
    	if (Find(t) != Find(n + 1)) { puts("0"); return 0; }
    	for (tim = 1; ; tim++)
    	{
    		Add(s, Id(tim - 1, n + 1), INF);
    		for (int i = 1; i <= m; i++) 
    		{
    			int pos1 = tim % a[i][0] == 0 ? a[i][0] : tim % a[i][0], pos2 = (tim + 1) % a[i][0] == 0 ? a[i][0] : (tim + 1) % a[i][0];
    		//	if (a[i][pos1] == t) continue;
    			Add(Id(tim - 1, a[i][pos1]), Id(tim, a[i][pos2]), b[i]);
    		}
    		while(Bfs())
    		{
    			maxflow += Dinic(s, INF);
    		}
    		if (maxflow >= k) { Put(tim); return 0; }
    		for (int i = 1; i <= n + 1; i++) Add(Id(tim - 1, i), Id(tim, i), INF);
    	}
    	return 0;
    }
    
  • 相关阅读:
    Enterprise Library Step By Step系列(一):配置应用程序块——入门篇
    Enterprise Library Step By Step系列(八):日志和监测应用程序块——进阶篇
    在ASP.NET页面中冻结DataGrid的列或头部
    数据库设计技巧系列(五)——各种小技巧
    用任务计划实现数据库的异地备份
    如何更好的与人沟通?[图]
    在Asp.net中如何用SQLDMO来获取SQL Server中的对象信息
    SQL Server 2012 Express LocalDB
    Clay: 创建和使用深层次对象图
    VS 2012 的 单元测试 和 测试资源管理器
  • 原文地址:https://www.cnblogs.com/Tian-Xing-Sakura/p/13097983.html
Copyright © 2011-2022 走看看