zoukankan      html  css  js  c++  java
  • Annual Congress of MUD

    Annual Congress of MUD

    时间限制: 1 Sec  内存限制: 128 MB

    题目描述

    Multiuser dungeon games, also called MUD games, are real-time virtual-world multiplayer games that are usually played online with text-based commands. The players do not meet normally, but every year, there is the Annual Congress of MUD (ACM) where MUD lovers all around the world could meet in person.
    ACM is so popular that the event each year spans around 20 days. Each day, there will be a special gathering for MUD game designers to introduce their new games to the others. 
    Each player will usually spend a few days on the ACM site, and in-between will be invited in exactly one day to join this special gathering.
    This year, ACM is held at your city, and your boss is an organiser, and he wants to find a best way to assign the players to these special gatherings (one player to one special gathering within his or her duration of stay), so that the maximum number of players among all gatherings is minimized.
    Your boss is an extremely impatient guy. He wants to have a system that can tell the maximum number of players among all gatherings, in any best assignment, after each player enters his or her duration of stay. Your task is to help your boss develop such a system.

    输入

    An instance of the problem consists of N + 1 lines. The first line specifies the integers N and D, seperated by a space. In the ith line of the following N lines, it contains two integers xi and yi , separated by a space. Note that the test data file may contain more than one instance. The last instance is followed by a line containing a single 0.

    输出

    For each instance, an integer i is marked if and only if the maximum number of players in the best assignment increases after the duration of stay [xi , yi ] of the ith player is keyed in. By default, 1 is always marked. The output of the corresponding instance is the list of all marked integers in ascending order, separated by a space between successive integers, followed by a newline character.

    样例输入

    3 3
    1 1
    1 1
    1 1
    3 3
    1 2
    2 3
    1 1
    3 3
    1 2
    1 2
    1 2
    0
    

    样例输出

    1 2 3
    1
    1 3
    

    提示

    1.The number of players joining the congress, N, is an integer with 1 ≤ N ≤ 10000.
    2.The number of days, D, of the congress is an integer with 3 ≤ D ≤ 20.
    3.The duration of stay, [xi , yi ], for the ith player to be keyed in your system, are pairs of integers with 1 ≤ xi ≤ yi ≤ D. This indicates that the ith player will stay from day xi (inclusive) to day yi (inclusive) on the ACM site.


    题意:

    嘉年华一共有D天,每个人在[xi,yi]这几天来玩,每天都有一次盛会,但一个人必须且仅能参加一次盛会,我们希望盛会人数最多的时候最少,设这个数为T,这样可以平衡盛会出席的人数。现在给定n个人按顺序申请来玩的时间,如果某个人申请来玩后T会增加,输出这个人的编号。

    思路:

    对于前i个人我们都要求出局部的最优解,并判断T是否增加(T一次最多增加1)。那么我们跑最大流即可。源点连向人,容量为1,人连向能去的那些天,容量为1,每天连向汇点,容量为盛会人数最多可能多少人。(ps:这个多少人如果我们只要求全局的最优,那么二分即可。)如果最大流不满流,就是最大流不等于当前的人数,连向汇点的边容量+1就一定能满流了。注意这样连边显然会TLE。我们修改构图,鉴于整个图容量为1的边很多,我们直接构造(D+1)*D/2个点表示区间,区间连向包含的天,容量为INF。那么我们每次加人,就相当于源点连向某个区间的边的容量+1。这样点的数量就相当少了。

    一些优化:

    上面的写法可能还是会TLE,需要一些优化。

    1.每次跑最大流的时候,不需要重新构图跑,只要在残余网络上加上新建的边,再继续跑最大流就好了,每次都把这个流量累加起来。

    2.因为每次跑最大流的时候我们就增加了一条路径,所以dinic算法的bfs函数会消耗很多时间,可以用EK算法代替跑最大流。(dinic弧优化也可以过,但是比较慢)。

    3.因为n的数量很大,所以从源点连的边数也很大,所以我们要尽量重用某些边,如果新加的边已经存在,直接把它的容量加上新边的容量就行,否则才新加边。

    300ms+,EK算法:

    #include<bits/stdc++.h>
    #define INF INT_MAX/2
    using namespace std;
    const long long maxn=305;
    struct Edge
    {
        long long from,to,cap,flow;
        Edge(long long u,long long v,long long c,long long f):from(u),to(v),cap(c),flow(f) {}
    };
    struct EdmondsKarp
    {
        vector<Edge> edges;
        vector<long long> G[maxn];
        long long a[maxn];
        long long p[maxn];
        long long m;
     
        void init(int n)
        {
            for(long long i=0;i<=n;i++)
                G[i].clear();
                edges.clear();
                m=0;
        }
     
        void AddEdge(long long from,long long to,long long cap)
        {
            edges.push_back(Edge(from,to,cap,0));
            edges.push_back(Edge(to,from,0,0));
            G[from].push_back(m++);
            G[to].push_back(m++);
        }
     
        long long Maxflow(long long s,long long t)
        {
            long long flow=0;
            while(true)
            {
                memset(a,0,sizeof(a));
                queue<long long> Q;
                Q.push(s);
                a[s]=LLONG_MAX;
                while(!Q.empty())
                {
                    long long x=Q.front();
                    Q.pop();
                    for(long long i=0;i<G[x].size();i++)
                    {
                        Edge& e = edges[G[x][i]];
                        if(!a[e.to]&&e.cap>e.flow)
                        {
                            p[e.to]=G[x][i];
                            a[e.to]=min(a[x],e.cap-e.flow);
                            Q.push(e.to);
                        }
                    }
                    if(a[t])
                        break;
                }
                if(!a[t])
                    break;
                for(long long u=t;u!=s;u=edges[p[u]].from)
                {
                    edges[p[u]].flow+=a[t];
                    edges[p[u]^1].flow-=a[t];
                }
                flow+=a[t];
            }
            return flow;
        }
    };
     
    EdmondsKarp anss;
     
    int x[10050],y[10050];
    int vis[305][305]={0};
    int num_edg[305][305];
     
    int main()
    {
        int n,S,T,cur_clk=0;
     
        while(scanf("%d",&n)==1)
        {
            if(n==0)return 0;
            cur_clk++;
     
            int d;
            scanf("%d",&d);
            for(int i=1;i<=n;i++)scanf("%d %d",&x[i],&y[i]);
     
            int num[25][25]={0},Num=0;
     
            for(int i=1;i<=d;i++)
                for(int j=i;j<=d;j++)
                num[i][j]=++Num;
     
                S=++Num;
                T=++Num;
     
                anss.init(Num);
     
                for(int i=1;i<=d;i++)
                for(int j=i;j<=d;j++)
                for(int k1=i;k1<=j;k1++)
                if(i!=j)
                anss.AddEdge(num[i][j],num[k1][k1],INF);
     
                int ans[10010],sum_ans=0;
                int now_flow=0;
     
                int now_edge=anss.m;
                for(int i=1;i<=d;i++)
                anss.AddEdge(num[i][i],T,0);
     
                for(int i=1;i<=n;i++)
                {
                    if(vis[x[i]][y[i]]!=cur_clk)
                    {
                        vis[x[i]][y[i]]=cur_clk;
                        anss.AddEdge(S,num[x[i]][y[i]],1);
                        num_edg[x[i]][y[i]]=anss.m-2;
                    }
                    else
                        anss.edges[num_edg[x[i]][y[i]]].cap++;
     
                    now_flow+=anss.Maxflow(S,T);
                    if(now_flow!=i)
                    {
                        ans[sum_ans++]=i;
     
                           for(int i=0;i<2*d;i+=2)
                            anss.edges[now_edge+i].cap++;
                    }
                }
     
                for(int i=0;i<sum_ans;i++)printf("%d ",ans[i]);
                printf("
    ");
     
        }
        return 0;
    }
    View Code

    700ms+,Dinic算法

    #include<bits/stdc++.h>
    #define N 305
    #define INF INT_MAX/2
    using namespace std;
    typedef struct
    {
        int v;
        int flow;
    }ss;
     
    ss edg[N*N];
    int edges[N][N];
     
    int now_edges=0;
     
    void addedge(int u,int v,int flow)
    {
        edges[u][++edges[u][0]]=now_edges;
        edg[now_edges++]=(ss){v,flow};
        edges[v][++edges[v][0]]=now_edges;
        edg[now_edges++]=(ss){u,0};
    }
     
    int dis[N],S,T;
    int q[10000];
     
    bool bfs()
    {
        memset(dis,0,sizeof(dis));
        int c1=0,c2=1;
        q[0]=S;
        dis[S]=1;
     
        while(c1<c2)
        {
            int now=q[c1];
            c1++;
            int Size=edges[now][0];
     
            for(int i=1;i<=Size;i++)
            {
                ss e=edg[edges[now][i]];
                if(e.flow>0&&dis[e.v]==0)
                {
                    dis[e.v]=dis[now]+1;
                    q[c2++]=e.v;
                }
            }
        }
        if(dis[T]==0)return 0;
        return 1;
     
    }
    int current[N];
     
    int dfs(int now,int maxflow)
    {
     
        if(now==T)return maxflow;
        int Size=edges[now][0];
     
        for(int i=current[now];i<=Size;i++)
        {
            current[now]=i;
            ss &e=edg[edges[now][i]];
     
            if(e.flow>0&&dis[e.v]==dis[now]+1)
            {
                int Flow=dfs(e.v,min(maxflow,e.flow));
     
                if(Flow)
                {
     
                    e.flow-=Flow;
                    edg[edges[now][i]^1].flow+=Flow;
                    return Flow;
                }
            }
        }
        return 0;
    }
     
    int dinic()
    {
        int ans=0,flow;
        while(bfs())
        {
            for(int i=0;i<N;i++)current[i]=1;
            while(flow=dfs(S,INF))ans+=flow;
        }
     
        return ans;
    }
     
    void init(int n)
    {
        now_edges=0;
        for(int i=0;i<=n;i++)edges[i][0]=0;
    }
     
    int x[10050],y[10050];
    int vis[305][305]={0};
    int num_edg[305][305];
     
    int main()
    {
        int n,cur_clk=0;
     
        while(scanf("%d",&n)==1)
        {
            if(n==0)return 0;
            cur_clk++;
     
            int d;
            scanf("%d",&d);
            for(int i=1;i<=n;i++)scanf("%d %d",&x[i],&y[i]);
     
            int num[25][25]={0},Num=0;
     
            for(int i=1;i<=d;i++)
                for(int j=i;j<=d;j++)
                num[i][j]=++Num;
     
                S=++Num;
                T=++Num;
     
                init(Num);
     
                for(int i=1;i<=d;i++)
                for(int j=i;j<=d;j++)
                for(int k1=i;k1<=j;k1++)
                if(i!=j)
                addedge(num[i][j],num[k1][k1],INF);
     
                int ans[10010],sum_ans=0;
                int now_flow=0;
     
                int now_edge=now_edges;
                for(int i=1;i<=d;i++)
                addedge(num[i][i],T,0);
     
                for(int i=1;i<=n;i++)
                {
                    if(vis[x[i]][y[i]]!=cur_clk)
                    {
                        vis[x[i]][y[i]]=cur_clk;
                        num_edg[x[i]][y[i]]=now_edges;
                        addedge(S,num[x[i]][y[i]],1);
                    }
                    else
                        edg[num_edg[x[i]][y[i]]].flow++;
     
                    now_flow+=dinic();
                    if(now_flow!=i)
                    {
                        ans[sum_ans++]=i;
     
                           for(int i=0;i<2*d;i+=2)
                            edg[now_edge+i].flow++;
                    }
                }
     
                for(int i=0;i<sum_ans;i++)printf("%d ",ans[i]);
                printf("
    ");
     
        }
        return 0;
    }
    View Code
  • 相关阅读:
    [BTS] BizTalk WCF-SQL Adapter 高级应用
    [BTS] BizTalk EDI character set and separator settings
    [ThingWorx] Install Guideline
    [ThingWorx] Install PostgreSQL Issue
    [BTS] BizTalk EDI AS2 Error 1
    [BTS] BizTalk With EF
    [BTS] Exception occurred when persisting state to the database
    [BTS] MSDTC
    [BTS] The value "" for the property InboundId is invalid
    [Android] Android Sutdio on Surface Pro 3
  • 原文地址:https://www.cnblogs.com/tian-luo/p/9545725.html
Copyright © 2011-2022 走看看