二分图——《算法艺术与信息学竞赛》

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;
}








写的不是很有条例 。






















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值