POJ 3084
来源:互联网 发布:linux复制多个文件 编辑:程序博客网 时间:2024/06/06 04:57
第一道最大流的题, 网络流的题都是图不好建立, 一般能想到怎么建图,题就过了
给你一些房间,和房间之间的关系,
问你至少需要关几个门,才能是你想保卫的房间不受到侵犯;
样例解释:
m->room numbers , n->the room number that you want to defence
(room numbre from 0 to m-1)
char -> the room whether have an intruder or not c-> the numbre of the rooms it can go freely xi -> the room's number
解题思路
抽象成一个最大流问题,房间看成点, 门看成边,如果此房间有别的房间的钥匙,那么无论关上几扇门都没有作用,所以流量就是INF, 但是如果这个房间没有别的房间的钥匙,那么它与别的房间的流量就是1(在存在门的前提下,只可以通过门进入),求最大流,就是至少需要关闭的门数才能保证指定的房间不收侵犯
算法 : ISPA
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
using namespace std;
#define MAXN 20000
#define MAXM 2000002
#define INF 0x1f1f1f
struct Edge
{
int u, v, c;
int next;
Edge(){};
Edge( int tu, int tv, int tc, int tn):u(tu), v(tv), c(tc), next(tn){};
};
Edge E[MAXM * 3];
int head[MAXN], cur[MAXN], que[MAXN], cnt[MAXN],d[MAXN],low[MAXN], nE;
int vis[MAXN];
void initNetWork()
{
memset(head, -1, sizeof(head));
nE = 0;
}
void addEdge( int u, int v, int c, int rc = 0)//rc 反向弧流量, c正向弧流量
{
E[nE] = Edge(u, v, c, head[u]);
head[u] = nE++;
E[nE] = Edge(v, u, rc, head[v]);
head[v] = nE++;
}
int maxflow( int n, int source, int sink)
{
//bfs 算出d[i]的最小值
//d[i]表示每个顶点I到源点的无权最短距离(隔几个点)
int *fr = que, *ta = que;
for( int i = 0; i < n; i++)
d[i] = n, cnt[i] = 0;
cnt[0]++, d[sink] = 0;
cnt[n] = n-1;
*ta++ = sink;
while( fr < ta)
{
int v = *fr++;
for( int i = head[v];i != -1; i = E[i].next)
{
//d[E[i].v] == n 表示E[i].v没有访问过
if(d[E[i].v] == n && E[i^1].c > 0)
{
d[E[i].v] = d[v] + 1;
cnt[n]--;
cnt[d[E[i].v]] ++;
*ta ++ = E[i].v;
}
}
}
int u = source, top = 0, flow = 0;
low[0] = INF;
cnt[0] = n;
//memcpy(cur, head, sizeof(head));
for( int i = 0; i < n ; i++)
cur[i] = head[i];
while(d[source] < n)
{
int &i = cur[u];
for(; i != -1; i = E[i].next)
{
if(E[i].c > 0 && d[u] == d[E[i].v] + 1)
{
low[top + 1] = low[top] < E[i].c ? low[top] : E[i].c;
que[++top] = i;//QUE存的是边
u = E[i].v;
break;
}
}
if(i != -1)
{
if( u == sink)
{
int delta = low[top];
for( int p = 1,i; p <= top ;p++)
{
i = que[p];
E[i].c -= delta;
E[i^1].c += delta;
}
flow += delta;
low[0] = INF;
top = 0;
u = source;
}
}
else
{
int old_du = d[u];
cnt[old_du] --;
d[u] = n -1 ;
for( int i = head[u]; i != -1; i = E[i].next)
{
if(E[i].c > 0 && d[u] > d[E[i].v])
d[u] = d[E[i].v];
}
cnt[++d[u]]++;
if(d[u] < n)
cur[u] = head[u];
if(u != source)
{
u = E[que[top]].u;
top--;
}
if(cnt[old_du] == 0)
break;
}
}
return flow;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
initNetWork();
int m,n;
scanf("%d %d",&n, &m);
char s[5];
int c, u, v;
int ss = n, tt = m;
getchar();
for( int i = 0; i < n; i++)
{
scanf("%s%d",s, &c);
if(strcmp(s,"I") == 0)
addEdge(ss, i, INF,1);
while(c--)
{
scanf("%d",&v);
addEdge( i, v, INF,1);
}
}
int ans = maxflow(n+1, ss, tt);
if(ans >= INF)
printf("PANIC ROOM BREACH\n");
else
printf("%d\n",ans);
}
return 0;
}
- POJ 3084
- POJ 3084 Panic Room
- poj 3084(最小割。。。。。)
- POJ 3084 最大流
- poj 3084 Panic Room
- poj 3084 Dinic
- poj 3084 最小割
- poj 3084(最小割)
- poj 3084 最小割
- poj 3084(最小割)
- POJ 3084 Panic Room
- POJ
- poj
- POJ
- POJ
- poj
- poj
- POJ
- C/C++
- JIRA安装破解汉化
- ActiveMQ InactivityIOException: Channel was inactive for too (>30000) long 处理方案
- Unity3D PC版本打包
- ios ALAsset和ALAssetRepresentation详解
- POJ 3084
- WEKA使用教程(经典教程转载)
- 百度笔试题:malloc/free与new/delete的区别
- Android图片处理:识别图像方向并显示
- POJ 2135(Farm Tour-费用流)[Template:费用流 V2]
- 高通AR增强现实Unity3D
- ios UIScrollView自动滚动 循环滚动视图实现
- 自己对工作的总结,总自己的认识,我不怕累的哦
- 《Swift权威指南》学习笔记(一)