hdu3549Flow_Problem
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 5005;
const int M = 30005;
struct Enode{
int y, c, next;
} e[M * 2];
//struct Point
//{
// int son,cur,pre,lim,d;
//} a[maxn];
int n, m, tot, head[N], now[N], h[N], vh[N], augc, found, flow;
//h为距离,vh为距离标号的数目,augc当前边的流量,flow总流量
//int tot, n, m, st, ed, cnt[maxn];
void Addedge(int x, int y, int c){
e[++tot].y = y; e[tot].c = c; e[tot].next = head[x]; head[x] = tot;
e[++tot].y = x; e[tot].c = 0; e[tot].next = head[y]; head[y] = tot;
}
void Init(){
int x, y, c, i;
scanf("%d%d", &n, &m);
tot = -1; memset(head, -1, sizeof(head));
for (i = 0; i < m; i++){
scanf("%d%d%d", &x, &y, &c);
Addedge(x, y, c);
}
memcpy(now, head, sizeof(head));
}
void Aug(int x, int st, int ed, int n){//x当前点,st源点,ed汇点,n,点最大数目
int p = now[x], minh = n - 1, augco = augc;
if (x == ed){
found = 1;
flow += augc;
return;
}
while (p != -1){//每条边
if (e[p].c > 0 && h[e[p].y] + 1 == h[x]){//e[p].y下一点,可行弧
augc = min(augc, e[p].c);
Aug(e[p].y, st, ed, n);//下一点
if (h[st] >= n) return;
if (found) break;
augc = augco;
}
p = e[p].next;//下一边
}
if (found){
e[p].c -= augc;
e[p ^ 1].c += augc;//边标号从0开始,反向边,p^1
}else{
p = head[x];
while (p != -1){
if (e[p].c > 0 && h[e[p].y] < minh){
minh = h[e[p].y];//最小标号
now[x] = p;
}
p = e[p].next;
}
vh[h[x]] --;//标号数目-1
if (!vh[h[x]]) h[st] = n;//无符合标号
h[x] = minh + 1;//修改当前节点标号
vh[h[x]] ++;
}
}
void Maxflow(int st, int ed, int n){
flow = 0;
memset(h, 0, sizeof(h));
memset(vh, 0, sizeof(vh));
vh[0] = n;//距离标号的数目
while (h[st] < n){
found = 0;
augc = 1 << 30;//假设流量无穷大
Aug(st, st, ed, n);
}
}
int main(){
int T,cas=0;
scanf("%d",&T);
while(T--){
Init();
Maxflow(1, n, n);
printf("Case %d: %d\n",++cas, flow);
}
return 0;
}
poj1273Drainage Ditches
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
#define MAXN 2222
#define MAXM 444444 //邻接表要开边数的2倍
#define inf 1<<30
struct Edge {
int v,cap,next;
} edge[MAXM];
int n,m,vs,vt,NE,NV;
int head[MAXN];
void Insert(int u,int v,int cap)
{
edge[NE].v=v;
edge[NE].cap=cap;
edge[NE].next=head[u];
head[u]=NE++;
edge[NE].v=u;
edge[NE].cap=0;
edge[NE].next=head[v];
head[v]=NE++;
}
int level[MAXN];//标记层次(距离标号)
int gap[MAXN];
//间隙优化,定义gap[i]为标号是i的点的个数
//在重标记i时,检查gap[level[i]],若减为0,这算法结束。
void bfs(int vt)
{
memset(level,-1,sizeof(level));
memset(gap,0,sizeof(gap));
level[vt]=0;
gap[level[vt]]++;
queue<int>que;
que.push(vt);
while(!que.empty()) {
int u=que.front();
que.pop();
for(int i=head[u]; i!=-1; i=edge[i].next) {
int v=edge[i].v;
if(level[v]!=-1)continue;
level[v]=level[u]+1;
gap[level[v]]++;
que.push(v);
}
}
}
int pre[MAXN];//前驱
int cur[MAXN];
int SAP(int vs,int vt)//源点,汇点
{
bfs(vt);//bfs优化,
memset(pre,-1,sizeof(pre));
memcpy(cur,head,sizeof(head));//cur保存的是当前弧
int u=pre[vs]=vs,flow=0,aug=inf;//源点前驱还是它本身,aug表示增广路的可改尽量
gap[0]=NV;
while(level[vs]<NV) {
bool flag=false;
for(int &i=cur[u]; i!=-1; i=edge[i].next) {
int v=edge[i].v;//v是u的后继
//寻找可行弧
if(edge[i].cap&&level[u]==level[v]+1) {
flag=true;//找到可行弧
pre[v]=u;//记录前驱
u=v;
// aug=(aug==-1?edge[i].cap:min(aug,edge[i].cap));
aug=min(aug,edge[i].cap);
//如果找到 一条增广路
if(v==vt) {
flow+=aug;//更新最大流
for(u=pre[v]; v!=vs; v=u,u=pre[u]) {
edge[cur[u]].cap-=aug;//前向弧容量减少
edge[cur[u]^1].cap+=aug;//后向弧容量增加
}
// aug=-1;
aug=inf;
}
break;
}
}
if(flag)continue;
int minlevel=NV;
//寻找与当前点相连接的点中最小的距离标号(重标号)
for(int i=head[u]; i!=-1; i=edge[i].next) {
int v=edge[i].v;
if(edge[i].cap&&level[v]<minlevel) {
minlevel=level[v];
cur[u]=i;
}
}
if(--gap[level[u]]==0)break;//更新gap数组后若出现断层,直接退出
level[u]=minlevel+1;//重标号
gap[level[u]]++;//距离标号为level[u]的点的个数+1
u=pre[u];//转为当前节点的前驱继续寻找可行弧
}
return flow;
}
int main()
{
int u,v,w,w1,w2;
while(scanf("%d%d",&m,&n)==2){
vs=0;
vt=n-1;
NV=n;//总点数
NE=0;
memset(head,-1,sizeof(head));
for(int i=1; i<=m; i++) {
scanf("%d%d%d",&u,&v,&w);
Insert(--u,--v,w);
//Insert(v,u,w);
}
printf("%d\n",SAP(vs,vt));
}
return 0;
}
poj3281Dining
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 5005;
const int M = 30005;
struct Enode{
int y, c, next;
} e[M * 2];
//struct Point
//{
// int son,cur,pre,lim,d;
//} a[maxn];
int n, m, tot, head[N], now[N], h[N], vh[N], augc, found, flow;
//h为距离,vh为距离标号的数目,augc当前边的流量,flow总流量
//int tot, n, m, st, ed, cnt[maxn];
void Addedge(int x, int y, int c){
e[++tot].y = y; e[tot].c = c; e[tot].next = head[x]; head[x] = tot;
e[++tot].y = x; e[tot].c = 0; e[tot].next = head[y]; head[y] = tot;
}
int f,d;
void Init(){
int x, y, c, i,tmp;
scanf("%d%d%d", &n, &f, &d);
tot = -1; memset(head, -1, sizeof(head));
for (i = 1; i <= n; i++){
scanf("%d%d", &x, &y);
while(x--){
scanf("%d",&tmp);
Addedge(0,tmp,1);
//Addedge(tmp,f+i,1);在这里可能会加重了
}
Addedge(i+f,i+f+n,1);
while(y--){
scanf("%d",&tmp);
Addedge(i+n+f,f+2*n+tmp,1);
//Addedge(f+2*n+tmp,f+2*n+d+1,1);
}
}
for(int j=1;j<=f;j++) Addedge(j,i+f,1);
for(int j=1;j<=d;j++) Addedge(j+f+n*2,d+f+n*2+1,1);
memcpy(now, head, sizeof(head));
}
void Aug(int x, int st, int ed, int n){//x当前点,st源点,ed汇点,n,点最大数目
int p = now[x], minh = n-1, augco = augc;
if (x == ed){
found = 1;
flow += augc;
return;
}
while (p != -1){//每条边
if (e[p].c > 0 && h[e[p].y] + 1 == h[x]){//e[p].y下一点,可行弧
augc = min(augc, e[p].c);
Aug(e[p].y, st, ed, n);//下一点
if (h[st] >= n) return;
if (found) break;
augc = augco;
}
p = e[p].next;//下一边
}
if (found){
e[p].c -= augc;
e[p ^ 1].c += augc;//边标号从0开始,反向边,p^1
}else{
p = head[x];
while (p != -1){
if (e[p].c > 0 && h[e[p].y] < minh){
minh = h[e[p].y];//最小标号
now[x] = p;
}
p = e[p].next;
}
vh[h[x]] --;//标号数目-1
if (!vh[h[x]]) h[st] = n;//无符合标号
h[x] = minh + 1;//修改当前节点标号
vh[h[x]] ++;
}
}
void Maxflow(int st, int ed, int n){
flow = 0;
memset(h, 0, sizeof(h));
memset(vh, 0, sizeof(vh));
vh[0] = n;//距离标号的数目
while (h[st] < n){
found = 0;
augc = 1 << 30;//假设流量无穷大
Aug(st, st, ed, n);
}
}
int main(){
Init();
Maxflow(0, 2*n+f+d+1, 2*n+f+d+2);
printf("%d\n", flow);
}
sgu185
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
#define MAXN 444
#define MAXM 160002 //邻接表要开边数的2倍
#define inf 1<<30
#define INF 1<<30
#define maxn 444
bool vis[maxn];
int adj[maxn][maxn],dis[maxn];//pre[]记录前驱
int n, m;
void dijkstra(int v)
{
int i, j, u , min;
for(i=0;i<=n;i++) {
dis[i]=adj[v][i];
vis[i]=0;
}
vis[v]=1;dis[v]=0;
for(i=1;i<=n;i++) {
min = INF;
for(j=1;j<=n;j++)
if(!vis[j]&&min > dis[j]){
min = dis[j];
u = j;
}
if(min == INF)break;
vis[u]=1;
for(j=1;j<=n;j++){
if(!vis[j]&&adj[u][j]!=INF&&dis[u]+adj[u][j]<dis[j])
dis[j] = adj[u][j] + dis[u];
}
}
}
struct Edge {
int v,cap,next;
} edge[MAXM];
int vs,vt,NE,NV;
int head[MAXN];
void Insert(int u,int v,int cap)
{
edge[NE].v=v;
edge[NE].cap=cap;
edge[NE].next=head[u];
head[u]=NE++;
edge[NE].v=u;//反向边
edge[NE].cap=0;
edge[NE].next=head[v];
head[v]=NE++;
}
void make_graph(){
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++){
if(i==j||adj[i][j]==INF) continue;
if(dis[i]+adj[i][j]==dis[j]){
Insert(i-1,j-1,1);
//Insert(j-1,i-1,1);
//printf("edge:%d %d\n",i,j);
}
}
}
int level[MAXN];//标记层次(距离标号)
int gap[MAXN];
//间隙优化,定义gap[i]为标号是i的点的个数
//在重标记i时,检查gap[level[i]],若减为0,这算法结束。
void bfs(int vt)
{
memset(level,-1,sizeof(level));
memset(gap,0,sizeof(gap));
level[vt]=0;
gap[level[vt]]++;
queue<int>que;
que.push(vt);
while(!que.empty()) {
int u=que.front();
que.pop();
for(int i=head[u]; i!=-1; i=edge[i].next) {
int v=edge[i].v;
if(level[v]!=-1)continue;
level[v]=level[u]+1;
gap[level[v]]++;
que.push(v);
}
}
}
int pre[MAXN];//前驱
int cur[MAXN];
int SAP(int vs,int vt)//源点,汇点
{
bfs(vt);//bfs优化,
memset(pre,-1,sizeof(pre));
memcpy(cur,head,sizeof(head));//cur保存的是当前弧
int u=pre[vs]=vs,flow=0,aug=inf;//源点前驱还是它本身,aug表示增广路的可改尽量
gap[0]=NV;
while(level[vs]<NV) {
bool flag=false;
for(int &i=cur[u]; i!=-1; i=edge[i].next) {
int v=edge[i].v;//v是u的后继
//寻找可行弧
if(edge[i].cap&&level[u]==level[v]+1) {
flag=true;//找到可行弧
pre[v]=u;//记录前驱
u=v;
// aug=(aug==-1?edge[i].cap:min(aug,edge[i].cap));
aug=min(aug,edge[i].cap);
//如果找到 一条增广路
if(v==vt) {
flow+=aug;//更新最大流
for(u=pre[v]; v!=vs; v=u,u=pre[u]) {
edge[cur[u]].cap-=aug;//前向弧容量减少
edge[cur[u]^1].cap+=aug;//后向弧容量增加
}
// aug=-1;
aug=inf;
}
break;
}
}
if(flag)continue;
int minlevel=NV;
//寻找与当前点相连接的点中最小的距离标号(重标号)
for(int i=head[u]; i!=-1; i=edge[i].next) {
int v=edge[i].v;
if(edge[i].cap&&level[v]<minlevel) {
minlevel=level[v];
cur[u]=i;
}
}
if(--gap[level[u]]==0)break;//更新gap数组后若出现断层,直接退出
level[u]=minlevel+1;//重标号
gap[level[u]]++;//距离标号为level[u]的点的个数+1
u=pre[u];//转为当前节点的前驱继续寻找可行弧
}
//cout<<'f'<<flow<<endl;
return flow;
}
bool flag;//flag的作用
void dfs(int u){///输出路径
if(flag) return ;
if(u==n-1){
flag=true;
cout<<endl;
return ;
}
for(int i=head[u];i!=-1&&!flag;i=edge[i].next){
int v=edge[i].v;
if(edge[i].cap==0 && !(i&1)){///
edge[i].cap=-1;
cout<<' '<<v+1;
dfs(v);
}
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=0;i<=n;i++)for(int j=0;j<=n;j++){
if(i==j)adj[i][j]=0;
else adj[i][j]=INF;
}
for(int i=1;i<=m;i++){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
adj[x][y]=adj[y][x]=z;
}
dijkstra(1);
//cout<<' '<<dis[n]<<endl;
vs=0;
vt=n-1;
NV=n;//总点数
NE=0;
memset(head,-1,sizeof(head));
make_graph();//位置= =
if(SAP(vs,vt)<2)printf("No solution\n");
else{
cout<<1;
flag=false;
dfs(0);
//cout<<'a'<<endl;
cout<<1;
flag=false;
dfs(0);
}
return 0;
}