poj 3084 最小割 模板题 PANIC ROOM
来源:互联网 发布:淘宝上心悦会员怎么刷 编辑:程序博客网 时间:2024/05/21 09:46
多校出了道模板题,于是就开始找模板。这题也是求最小割。
http://poj.org/problem?id=3084
题意:有n个房间,要确保一个房间(t)不能进坏人。相邻的房间可能会有门,但是门上的锁是单向的(只能从一个房间打开进入另一个房间,
a b ,只能从a进入b 不能从b 进入a),初始所有的锁都是开着的,问至少关上几个锁,才能不让坏人进入那个房间。
最小割?此前看到过最大流最小割定理,还以为是最大流的另一种求法呢,原来是用最大流的算法解决最小割问题。。。
构图还是关键:增加一个源点,不能进入坏人的房间(t)是汇点,如果某房间里本来有坏人,就连接这个房间和源点,
权值为inf,如果a->b想通,则a->b的权值为inf ,b->a权值为1(因为锁的控制权在a房间,如果坏人在a房间,这个门是
关不住的(inf),但是坏人如果在b房间,关上这个门只需锁一把锁(1),
还有就是重边问题,因为可能a->b一把锁,b->a一把锁。。。
这个模板是dfs的,估计不是很好。又找了个不是dfs的,还没来得及敲,又去搞代班的事了。
dfs的dinic:
#include <iostream>#include <cstring>#include <cstdio>#include <queue>#define inf 9999999#define Min(a,b) a < b ? a : busing namespace std;int head[25],level[25];int n,t,s_edge;struct Edge{ int to,w,nxt;}edge[1102];void addedge(int u, int v, int w1, int w2){ s_edge++; edge[s_edge] .to = v; edge[s_edge].w = w1; edge[s_edge].nxt = head[u]; head[u] = s_edge; s_edge++; edge[s_edge].to = u; edge[s_edge].w = w2; edge[s_edge].nxt = head[v]; head[v] = s_edge;}int dfs(int x, int cap){ //n inf if(x == t) return cap; int tmp = cap; for(int i = head[x]; i != -1; i = edge[i].nxt){ int to = edge[i].to; if(level[to] == level[x] + 1 && edge[i].w > 0 && tmp > 0){ int tt = dfs(to,Min(edge[i].w,tmp)); edge[i].w -= tt; edge[i ^ 1].w += tt; tmp -= tt; } } return cap - tmp;}int bfs(){ int i; memset(level,-1,sizeof(level)); queue<int > qu; level[n] = 0;//源点n是第0层 qu.push(n);//让源点进去 while(!qu.empty()){ int tt = qu.front(); qu.pop(); for(i = head[tt]; i != -1; i = edge[i].nxt){ int to = edge[i].to; if(level[to] == -1 && edge[i].w > 0){ level[to] = level[tt] + 1; qu.push(to); } } } if(level[t] != -1) return 1; return 0;}int dinic(){ int sum = 0; while(bfs()){ sum += dfs(n,inf);//源点 inf 。。。暂时的理解 } return sum;}int main(){ int ca ; char ch[5]; int num,k; scanf("%d",&ca); while(ca --){ scanf("%d%d",&n,&t); s_edge = 1; memset(head,-1,sizeof(head)); for(int i = 0; i < n; i ++){ scanf("%s",ch); if(ch[0] == 'I') addedge(n,i,inf,0);//n为源点 源点到有入侵者的点连个无穷大(锁不住),有入侵者的点到源点连个0(不需要锁) scanf("%d",&num); while(num --){ scanf("%d",&k); addedge(i,k,inf,1);//i 到 k 锁不住, k 到 i 需要一把锁 } } int ans = dinic(); if(ans < inf) //??? printf("%d\n",ans); else printf("PANIC ROOM BREACH\n"); } return 0;}
不是dfs的dinic:
#include<iostream>#include<cstdio>#include<string>using namespace std;#define inf 1<<30#define cc(m,v) memset(m,v,sizeof(m))struct node{ int u,v,f,next;}edge[1000];int head[30],p=0,lev[30],cur[30];int que[1000];void ainit(){ p=0,cc(head,-1);}bool bfs(int s,int t){ int i,u,v,qin=0,qout=0; cc(lev,0),lev[s]=1,que[qin++]=s; while(qout!=qin){ u=que[qout++]; for(i=head[u];i!=-1;i=edge[i].next) if(edge[i].f>0 && lev[v=edge[i].v]==0){ lev[v]=lev[u]+1,que[qin++]=v; if(v==t) return 1; } } return lev[t];}int dinic(int s,int t){ int qin=0,i,k,u,f; int flow=0; while(bfs(s,t)){ memcpy(cur,head,sizeof(head)); u=s,qin=0; while(1){ if(u==t){ for(k=0,f=inf;k<qin;k++) if(edge[que[k]].f<f) f=edge[que[i=k]].f; for(k=0;k<qin;k++) edge[que[k]].f-=f,edge[que[k]^1].f+=f; flow+=f,u=edge[que[qin=i]].u; } for(i=cur[u];cur[u]!=-1;i=cur[u]=edge[cur[u]].next) if(edge[i].f>0 && lev[u]+1==lev[edge[i].v]) break; if(cur[u]!=-1) que[qin++]=cur[u],u=edge[cur[u]].v; else{ if(qin==0) break; lev[u]=-1,u=edge[que[--qin]].u; } } } return flow;}void addedge(int u,int v){ edge[p].u=u,edge[p].v=v,edge[p].f=inf,edge[p].next=head[u],head[u]=p++; edge[p].u=v,edge[p].v=u,edge[p].f=1,edge[p].next=head[v],head[v]=p++;}int main(){ int cas,n,m,u,i,s,t; bool flag=0; char as[5]; scanf("%d",&cas); while(cas--){ ainit(); scanf("%d%d",&n,&t); for(flag=0,i=0,s=n;i<n;i++){ scanf("%s%d",as,&m); if(as[0]=='I'){ addedge(s,i); while(m--){ scanf("%d",&u); if(u==t) flag=1; addedge(i,u); } }else{ while(m--){ scanf("%d",&u); addedge(i,u); } } } if(flag){ cout<<"PANIC ROOM BREACH"<<endl;continue; } int flo=dinic(s,t); if(flo>=inf){ cout<<"PANIC ROOM BREACH"<<endl;continue; } printf("%d\n",flo); } return 0;}
- poj 3084 最小割 模板题 PANIC ROOM
- POJ 3084 Panic Room //最小割
- POJ 3084 Panic Room 最小割
- POJ 3084 Panic Room (最小割)
- POJ 3084 Panic Room | 最小割
- 【POJ】3084 Panic Room 最小割
- POJ 3084 Panic Room(最小割)
- POJ 3084 Panic Room 最小割
- POJ 3084 Panic Room(最小割)
- poj 3084 Panic Room 【最小割】
- POJ 3084 Panic Room 最小割
- poj--3084--Panic Room(最小割)
- poj 3084 Panic Room(最小割,边连通度)
- POJ 3084 - Panic Room【网络流 最小割】
- ZOJ 2788 Panic Room 最小割
- zoj 2788 Panic Room (最小割)
- zoj 2788 Panic Room(最小割)
- POJ 3084 Panic Room
- 我是如何在8周內自学编程的
- 职业路线图
- 经典的各类排序总结
- java.util.concurrent中文API
- HTML_03(javaScript(01))
- poj 3084 最小割 模板题 PANIC ROOM
- 算法题---求大神的思路
- Control 4289
- Android环境搭建遇到的问题总汇
- 程序员技术练级攻略
- [HTML]html表格制作 [大三TJB_708]
- 同步通信与异步通信区别
- 天天记录 - 双休安装双系统并搭建环境的悲惨遭遇
- IGMP Proxy