您的位置:首页 > 其它

HIhoder 永恒游戏

2015-06-19 17:01 246 查看


#1179 : 永恒游戏

时间限制:20000ms
单点时限:1000ms
内存限制:256MB


描述

很久很久以前,当Rowdark还是个善良的魔法师时,他在一个n个点m条边的无向图上玩一个游戏。
开始时他在一些点上放些石子。每次Rowdark选择一个点A,要求点A上的石子数大于等于邻居点个数。然后对A的每个邻居B,将A上的一个石子移到B上。如果不能选出这样的点A,那么游戏结束。Rowdark想知道这个游戏会不会无限循环。为了使问题更简单,你只需要求出是否10万轮后游戏仍然继续。


输入

第一行两个整数n和m(1 ≤ n ≤ 200)。
第二行n个整数a0, a1 ...
an-1表示每个点上的石子个数(0 ≤ ai ≤ 109)。
接下来m行,每行两个数x和y (x ≠ y, 0 ≤ x, y ≤ n - 1),表示在x和y之间有一条边。题目保证没有重边,且任意一个点都有邻居。


输出

如果Rowdark能玩超过100000轮,输出“INF”(不带引号),否则输出最多步数。

样例输入
3 3
1 2 1
0 1
1 2
2 0


样例输出
INF


#include <iostream>
#include <cstdio>
#include <string>
#include <vector>

using namespace std;
#define maxn 205

vector<int> G[maxn];
int n, m;
int a[maxn];

// Complexity is O(10^5 * n)

void solve()
{
    int cnt = 0;
    while(cnt <= 100000)
    {
        int u = -1;
        for(int i=0; i<n; i++)
            if(a[i] >= G[i].size())
        {
            u = i;
            break;
        }

        if(u == -1) break;

        int k = a[u]/G[u].size();
        a[u] -= k*G[u].size();
        cnt += k;
        for(int i=0; i<G[u].size(); i++)
        {
            int v = G[u][i];
            a[v] += k;
        }
    }

    if(cnt > 100000) printf("INF\n");
    else printf("%d\n", cnt);
}

int main()
{
    while(~scanf("%d%d", &n, &m))
    {
        for(int i=0; i<n; i++)
            {
                G[i].clear();
                scanf("%d", &a[i]);
            }

        for(int i=0; i<m; i++)
        {
            int u, v;
            scanf("%d%d", &u, &v);
            G[u].push_back(v);
            G[v].push_back(u);
        }

        solve();
    }

    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: