二分圖——《算法藝術與信息學競賽》

http://acm.timus.ru/problem.aspx?space=1&num=1155

原來的題目描述:


1155. Troubleduons

Time Limit: 0.5 second
Memory Limit: 16 MB
Archangel of the Science is reporting:
“O, Lord! Those physicists on the Earth have discovered a new elementary particle!”
“No problem, we’ll add another parameter to the General Equation of the Universe.”
As physics develops and moves on, scientists find more and more strange elementary particles, whose properties are more than unknown. You may have heard about muons, gluons and other strange particles. Recently scientists have found new elementary particles called troubleduons. These particles are called this way because scientists can create or annihilate them only in couples. Besides, troubleduons cause trouble to scientists, and that’s why the latter want to get rid of them. You should help scientists get rid of troubleduons.
Problem illustration
Experimental set consists of eight cameras, situated in the vertices of a cube. Cameras are named as A, B, C, …, H. It is possible to generate or annihilate two troubleduons in neighbouring cameras. You should automate the process of removing troubleduons.

Input

The only line contain eight integers ranging from 0 to 100, representing number of troubleduons in each camera of experimental set.

Output

Output sequence of actions leading to annihilating all troubleduons or “IMPOSSIBLE”, if you cannot do it. Actions should be described one after another, each in a separate line, in the following way: name of the first camera, name of the second camera (it should be a neighborough to the first one), “+” if you create troubleduons, “-” if you destroy them. Number of actions in the sequence should not exceed 1000.

Samples

input output
1 0 1 0 3 1 0 0 
EF-
EA-
AD+
AE-
DC-
0 1 0 1 2 3 2 2
IMPOSSIBLE
Problem Source: Ural Collegiate Programming Contest, April 2001, Perm, English Round 
Tags: none  (
hide tags for unsolved problems
)

題目大意描述:

一個正方體,各個頂點有一個初始值,(從0號頂點到7號頂點依次輸入數值)。相鄰頂點上的數值可以同增或同減。 

問能不能通過同增或同減,使所有數變成0。若不能,輸出“IMPOSSIBLE”,若能,則按上面的樣例輸出消去各個數的步驟。




解題:

我會告訴你這個題目是劉汝佳黑書上歸類於數論的題目麼?

我會告訴你要做這個題目,得到某國外網站註冊好不麻煩的麼?

我會告訴你這是個二分圖的題目麼?


二分圖:

這是個二分圖 !



代碼:


#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>

char adjj[100][10] = {"AB", "BC", "CD", "AD", "AE", "BF", "CG", "DH", "EF", "GF", "HG", "EH"};
int opp[10] = {6, 7, 4, 5, 2, 3, 0, 1};
int a[10];
int adj[10][10];
#define INF 99999999
using namespace std;
#define N 8

void build()
{
    memset(adj, 0, sizeof (adj));

    for (int j=  0; j < 12; j++)
        adj[ adjj[j][0] - 65]  [  adjj[j][1]   - 65] =  adj[ adjj[j][1] - 65]  [  adjj[j][0]   - 65] =1;
}

bool valid()
{
    if (a[0] + a[2] + a[5] + a[7]  == a[1] + a[3] + a[4] + a[6])
        return true;
    else
        return false;
}

void solve()
{
    bool flag;
    int max, min, o, index;
    max = -INF;
    for (int j = 0; j < N; j++)
        if (a[j] > max)
        {
            max = a[j];
            index = j;
        }

    for (int j = 0; j< N; j++)
        if (adj[index] [j])
        {
            for (int k = 0; k< N; k++)
                if (adj[j][k])
                {
                    min = a[j] < a[k] ? a[j] : a[k];

                    a[j] -= min;
                    a[k] -= min;

                    for (int p = 0; p < min; p++)
                        printf("%c%c-\n", (char)(j + 65), (char)(k + 65));
                }
            min = a[index] < a[j] ? a[index] : a[j];

            a[index] -= min;
            a[j]  -= min;

            for (int p = 0; p< min; p++)
                printf("%c%c-\n", (char)(index + 65), (char)(j + 65));
        }

    o = opp[index];

    for (int j = 0; j< N; j++)
        if (adj[o] [j])
        {
            for (int k = 0; k< N; k++)
                if (adj[j][k])
                {
                    min = a[j] < a[k] ? a[j] : a[k];

                    a[j] -= min;
                    a[k] -= min;

                    for (int p = 0; p < min; p++)
                        printf("%c%c-\n", (char)(j + 65), (char)(k + 65));
                }

            min = a[o] < a[j] ? a[o] : a[j];

            a[o] -= min;
            a[j] -= min;

            for (int p = 0; p < min; p++)
                printf("%c%c-\n", (char)(j + 65), (char)(o + 65));
        }

    flag = true;

    while (flag)
    {
        flag = false;
        for (int j = 0; j<N; j++)
            if (a[j] != 0)
            {
                flag = true;

//                for (int k = 0; k<N; k++)
//                {
//                    if (adj[j][k] && a[k] > 0)
//                    {
//                        min = a[j] < a[k] ? a[j] : a[k];
//
//                        a[j] -= min;
//                        a[k] -= min;
//                        for (int p = 0; p<min; p++)
//                            printf("%c%c-\n", (char)(j+65), (char)(k+65));
//                    }
//                }

                o = opp[j];
                for (int k = 0; k< N; k++)
                    if (adj[j][k])
                        for (int l=0; l<N; l++)
                            if (adj[k][l] && adj[l][o])
                            {
                                min = a[j] < a[o] ? a[j] : a[o];

                                a[j] -= min;
                                a[o] -= min;
                                for (int p=0; p<min; p++)
                                    printf("%c%c+\n%c%c-\n%c%c-\n", (char)(l+65), (char)(k+65),
                                           (char)(o+65),(char)(l+65),
                                           (char)(j+65),(char)(k+65));

                            }
            }
    }

}


int main()
{

    for (int j=  0; j <N; j++)
        cin >> a[j];

    if (  ! valid())
        cout << "IMPOSSIBLE" << endl;
    else
    {
        build();
        solve();
    }

    return 0;
}








寫的不是很有條例 。






















發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章