poj 1273.PIG 解题报告

网络流

关键是建图,思路在代码里

/*
      最大流SAP
      邻接表
      思路:基本源于FF方法,给每个顶点设定层次标号,和允许弧。
      优化:
      1、当前弧优化(重要)。
      1、每找到以条增广路回退到断点(常数优化)。
      2、层次出现断层,无法得到新流(重要)。
      时间复杂度(m*n^2)
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#define ms(a,b) memset(a,b,sizeof a)
using namespace std;
const int INF = 500;
int G[INF][INF];
struct node {
    int v, c, next;
} edge[INF*INF*4];
int  pHead[INF*INF], SS, ST, nCnt;
void addEdge (int u, int v, int c) {
    edge[++nCnt].v = v; edge[nCnt].c = c, edge[nCnt].next = pHead[u]; pHead[u] = nCnt;
    edge[++nCnt].v = u; edge[nCnt].c = 0, edge[nCnt].next = pHead[v]; pHead[v] = nCnt;
}
int SAP (int pStart, int pEnd, int N) {
    int numh[INF], h[INF], curEdge[INF], pre[INF];
    int cur_flow, flow_ans = 0, u, neck, i, tmp;
    ms (h, 0); ms (numh, 0); ms (pre, -1);
    for (i = 0; i <= N; i++) curEdge[i] = pHead[i];
    numh[0] = N;
    u = pStart;
    while (h[pStart] <= N) {
        if (u == pEnd) {
            cur_flow = 1e9;
            for (i = pStart; i != pEnd; i = edge[curEdge[i]].v)
                if (cur_flow > edge[curEdge[i]].c) neck = i, cur_flow = edge[curEdge[i]].c;
            for (i = pStart; i != pEnd; i = edge[curEdge[i]].v) {
                tmp = curEdge[i];
                edge[tmp].c -= cur_flow, edge[tmp ^ 1].c += cur_flow;
            }
            flow_ans += cur_flow;
            u = neck;
        }
        for ( i = curEdge[u]; i != 0; i = edge[i].next)
            if (edge[i].c && h[u] == h[edge[i].v] + 1)     break;
        if (i != 0) {
            curEdge[u] = i, pre[edge[i].v] = u;
            u = edge[i].v;
        }
        else {
            if (0 == --numh[h[u]]) continue;
            curEdge[u] = pHead[u];
            for (tmp = N, i = pHead[u]; i != 0; i = edge[i].next)
                if (edge[i].c)  tmp = min (tmp, h[edge[i].v]);
            h[u] = tmp + 1;
            ++numh[h[u]];
            if (u != pStart) u = pre[u];
        }
    }
    return flow_ans;
}
/*
       poj1149 最大流
       建图:
       每个顾客为一个节点,从源点到每个猪圈的第一个顾客连接一条容量为猪圈猪数目的边
       从第一个顾客到同一个猪圈的其它顾客连一条容量无限的边
       每个顾客到汇点的边的容量为他最大买的数量

*/
int k, c, m, n,x,y,z;
int vis[INF],sum[INF];
void solve(){
       nCnt=1;
       for(int i=1;i<=ST;i++)
       for(int j=1;j<=ST;j++){
              if(G[i][j]) addEdge(i,j,G[i][j]);
       }
       int ans=SAP(SS,ST,ST);
       printf("%d\n",ans);
}
int main() {
    /*
           先用邻接矩阵统计容量,再用前向星存边,表头在pHead[],初始化nCnt=1
           SS,ST分别为源点和汇点
    */
       scanf("%d %d",&m,&n);
       SS=n+1,ST=n+2;
       for(int i=1;i<=m;i++)
              scanf("%d",&sum[i]);
       for(int i=1;i<=n;i++){
              scanf("%d",&k);
              for(int j=1;j<=k;j++){
                     scanf("%d",&x);
                     if(!vis[x]){
                        G[SS][i]+=sum[x];
                        vis[x]=i;
                     }
                     else{
                        G[vis[x]][i]=0xffff;
                     }
              }
              scanf("%d",&k);
              G[i][ST]=k;
       }
       solve();
    return 0;
}

时间: 2024-12-19 07:26:16

poj 1273.PIG 解题报告的相关文章

poj 1469 COURSES 解题报告

题目链接:http://poj.org/problem?id=1469 题目意思:略 for 循环中遍历的对象要特别注意,究竟是遍历课程数P 还是 学生数N,不要搞混! 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std; 5 6 const int maxn = 300 + 5; 7 int match[maxn], map[maxn][maxn];

poj 1258 Agri-Net 解题报告

题目链接:http://poj.org/problem?id=1258 题目意思:给出 n 个 farm,每个farm 之间通过一定数量的fiber 相连,问使得所有farm 直接或间接连通的 最少 fiber 数是多少. 赤裸裸的最小生成树,用prim做的. 有个地方写错,wa 了 几次. 1 #include <iostream> 2 #include <cstdio> 3 using namespace std; 4 5 const int farm_num = 10000

poj 2923 Relocation 解题报告

题目链接:http://poj.org/problem?id=2923 题目意思:给出两部卡车能装的最大容量,还有n件物品的分别的weight.问以最优方式装入,最少能运送的次数是多少. 二进制表示物品状态:0表示没运走,1表示已被运走. 枚举出两辆车一趟可以运出的状态.由于物品是一趟一趟运出来的.所以就可以由一个状态通过两辆车一趟的状态转移到另一个状态. dp[i]=MIN(dp[k]+1).k可以由两车一趟转移到i. 我是参考此人的:http://blog.csdn.net/bossup/a

poj 2253 Frogger 解题报告

题目链接:http://poj.org/problem?id=2253 题目意思:找出从Freddy's stone  到  Fiona's stone  最短路中的最长路. 很拗口是吧,举个例子.对于 i 到 j 的一条路径,如果有一个点k, i 到 k 的距离 && k 到 j 的距离都小于 i 到 j 的距离,那么就用这两条中较大的一条来更新 i 到 j 的距离 .每两点之间都这样求出路径.最后输出 1 到 2 的距离(1:Freddy's stone   2:Fiona's sto

poj 1724 ROADS 解题报告

题目链接:http://poj.org/problem?id=1724 题目意思:给出一个含有N个点(编号从1~N).R条边的有向图.Bob 有 K 那么多的金钱,需要找一条从顶点1到顶点N的路径(每条边需要一定的花费),前提是这个总花费  <= K. 首先这里很感谢 yunyouxi0 ,也就是我们的ACM队长啦~~~,他一下子指出了我的错误——存储重边的错误.这条题卑鄙的地方是,有重边,discuss 中的数据过了也不一定会AC啦.大家不妨试试这组数据(队长深情奉献^_^) 2 2 2 1

【原创】poj ----- 1182 食物链 解题报告

题目地址: http://poj.org/problem?id=1182 题目内容: 食物链 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 48791   Accepted: 14222 Description 动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形.A吃B, B吃C,C吃A. 现有N个动物,以1-N编号.每个动物都是A,B,C中的一种,但是我们并不知道它到底是哪一种. 有人用两种说法对这N个

poj 1102.LC-Display 解题报告

题目链接:http://poj.org/problem?id=1102 题目意思:就是根据给出的格式 s 和 数字 n,输出数值 n 的 LCD 显示.数值 n 的每个数字要占据 s + 2 列 和 2s + 3 行.数字和数字之间要有一个空格.数值与数值之间有一个空行. 首先对于LCD 的 7 个笔画显示编上序号 然后对于数字 i,分析出占用了哪几个笔画,例如,数字 1 占有的笔画是 3 和 6:数字 6 占有的笔画是 1, 2, 4, 5, 6, 7 用数组来存储每一个笔画分别被那些数字占有

poj 2051.Argus 解题报告

题目链接:http://poj.org/problem?id=2051 题目意思:题目有点难理解,所以结合这幅图来说吧---- 有一个叫Argus的系统,该系统支持一个 Register 命令,输入就是类似样例中的: Register 2004 200 代表编号为 2004 的 Register,每隔 200 个时间单位就会产生一次.2005 同理.然后需要输出前 k 个事件.如果多个事件同时发生,就先输出编号较少的.所以在 600 这个时间上,2004 要比 2005 先输出. 第一次学 rj

poj 1861 Network 解题报告

Network Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 16171   Accepted: 6417   Special Judge Description Andrew is working as system administrator and is planning to establish a new network in his company. There will be N hubs in the c