裸奔 的傻瓜
在通往Ac的路上 蹒跚踱步

题目:http://acm.pku.edu.cn/JudgeOnline/problem?id=1087

 

 终于做到一个最大流的题目了,虽然我的图论是很水的(其实什么都比较水)。这个题目读懂之后,假设每个电器消耗的电能都是单位电能。这样就问题就转化成求插座组成的网络最大可以消耗掉的电能了。假设原始插座都连接至一个能量提供点,电器都连结至一个能量消耗点。这样就转化成简单的求网络最大流的问题。

 

 至于求最大流的过程,原先不是太懂。现在再学习一下。

cap[N][N],flow[N][N]。分别标记未被消耗的和已经消耗的。

1,2点分别标记起始点和终止点。

 

求图中一条通路,用dps的方法。从1点出发,找到一条到达2点的路即返回。

然后重新对cap,flow进行标记。直到没有通路被找到

 

#include <iostream>
#include <vector>
#define inf 100000

using namespace std;

int cap[420][420],flow[420][420];
int n_rec,n_item,n_adp;

char capp[420][30];
int path_find_index[1000];
vector<int> found_path;
int v_count,capp_count;
char ss[30];
int id_count=2;

int _find_path(int f)
{
    if(path_find_index[f]!=0) return 0;
    path_find_index[f]=1;
    int i;
    for (i=1;i<=v_count;i++)
    {
        if(cap[f][i]-flow[f][i]>0)
        {
            if(i==2)
            {
                found_path.push_back(2);
                found_path.push_back(f);
                return 1;
            }
            if(_find_path(i))
            {
                found_path.push_back(f);
                return 1;
            }
        }
    }
    path_find_index[f]=2;
    return 0;
}

int remain(int idf,int idt)
{
    return cap[idf][idt]-flow[idf][idt];
}

int find_path()
{
    for(int i=1;i<=v_count;i++) path_find_index[i]=0;
    found_path.clear();
    return _find_path(1);
}

int IsIn()
{
    for (int i=3;i<=id_count;i++)
    {
        if(!strcmp(capp[i],ss))
            return i;
    }
    return -1;
}

void plug()
{
    //capp_count=2;
    cin>>n_rec;

    int i,j;
    for(i=1;i<=310;i++)
        for(j=1;j<=310;j++)
        {
            cap[i][j]=flow[i][j]=0;
        }
    for (i=1;i<=n_rec;i++)
    {
        scanf("%s",ss);
        int cur=IsIn();
        if(cur==-1)
        {
            strcpy(capp[++id_count],ss);
            ++cap[1][id_count];
        }
        else
            ++cap[1][cur];
    }

    cin>>n_item;
    for (i=1;i<=n_item;i++)
    {
        scanf("%s",ss);
        scanf("%s",ss);
        int cur=IsIn();
        if (cur==-1)
        {
            strcpy(capp[++id_count],ss);
            ++cap[id_count][2];
        }
        else
            ++cap[cur][2];
    }

    cin>>n_adp;
    for (i=1;i<=n_adp;i++)
    {
        int idr,idf;
        scanf("%s",ss);
        int cur=IsIn();
        if (cur==-1)
        {
            strcpy(capp[++id_count],ss);
            idf=id_count;
        }
        else
            idf=cur;
        scanf("%s",ss);
        cur=IsIn();
        if (cur==-1)
        {
            strcpy(capp[++id_count],ss);
            idr=id_count;
        }
        else
            idr=cur;
        cap[idr][idf]=inf;
    }

    v_count=id_count;

    while (find_path())
    {
        int len=found_path.end()-found_path.begin();
        int i,tt;
        int cr=remain(found_path[len-1],found_path[len-2]);
        for (i=len-2;i>=1;i--)
        {
            tt=remain(found_path[i],found_path[i-1]);
            if(tt<cr) cr=tt;
        }
        for (i=len-1;i>=1;i--)
        {
            int idf,idt;
            idf=found_path[i];
            idt=found_path[i-1];

            flow[idf][idt]+=cr;
            flow[idt][idf]-=cr;
        }
    }

    int res=0;
    for (int i=3;i<=v_count;i++) res+=flow[1][i];
    printf("%d"n",n_item-res);
}

int main()
{
    freopen("test.txt","r",stdin);
    plug();
    return 0;
}

 

 另外就是读取的过程,要判断读进来的插座,是否已经存在。


posted on 2008-08-28 15:43  Lyt  阅读(507)  评论(0编辑  收藏  举报