顯示具有 network flow 標籤的文章。 顯示所有文章
顯示具有 network flow 標籤的文章。 顯示所有文章

2012年10月9日 星期二

UVA 11506 - Angry Programmer



  Angry Programmer 

You, a programmer of an important software house, have been fired because you didn't solve an important problem that was assigned to you. You are very furious and want to take revenge on your boss, breaking the communication between his computer and the central server.


The computer of your boss and the central server are in the same network, which is composed of many machines (computers) and wires linking pairs of those machines. There is at most one wire between any pair of machines and there can be pairs of machines without a wire between them.



To accomplish your objective, you can destroy machines and wires, but you can't destroy neither the computer of your boss nor the central server, because those machines are monitored by security cameras. You have estimated the cost of blowing up each machine and the cost of cutting each wire in the network.



You want to determine the minimum cost of interrupting the communication between your boss' computer and the central server. Two computers A and B can communicate if there is a sequence of undestroyed machines x1,..., xn such that x1 = A, xn = B and xi is linked with xi+1 with an uncut wire (for each 1 $ \leq$ i $ \leq$ n - 1 ).

Input 

The input consists of several test cases. Each test case is represented as follows:

  • A line with two integers M and W ( 2 $ \leq$ M $ \leq$ 50 , 0 $ \leq$ W $ \leq$ 1000 ), representing (respectively) the number of machines and the number of wires in the network.
  • M - 2 lines, one per machine (different from the boss' machine and the central server), containing the following information separated by spaces:
    • An integer i ( 2 $ \leq$ i $ \leq$ M - 1 ) with the identifier of the machine. Assume that the boss' machine has id 1 and that the central server has id M .
    • An integer c ( 0 $ \leq$ c $ \leq$ 100000 ) specifying the cost of destroying the machine.
  • W lines, one per wire, containing the following information separated by spaces:
    • Two integers j and k ( 1 $ \leq$ j < k $ \leq$ M ) specifying the identifiers of the machines linked by the wire. Remember that the wire is bidirectional.
    • An integer d ( 0 $ \leq$ d $ \leq$ 100000 ) specifying the cost of cutting the wire.



The end of the input is specified by a line with the string ``0 0''.



Suppose that the machines have distinct identifiers.

Output 

For each test case, print a line with the minimum cost of interrupting the communication between the computer of your boss and the central server.

Sample Input 


4 4
3 5
2 2
1 2 3
1 3 3
2 4 1
3 4 3
4 4
3 2
2 2
1 2 3
1 3 3
2 4 1
3 4 3
0 0

Sample Output 

4
3



Colombia'2008
network flow + 拆點
#include<stdio.h>
#include<cstring>
#include<string>
#include<vector>
#include<queue>
#define REP(i, b, n) for (int i = b; i < n; i++)
#define rep(i,n) REP(i, 0, n)
#define DBG 0
#define INF int(1e9)
#define MAXN 120
#define MAXM 5000
using namespace std;

int N,M,e,RES;
int next[MAXM],v[MAXM],cap[MAXM],head[MAXN];
int dis[MAXN],p[MAXN],pe[MAXN],q[MAXN],work[MAXN],pf[MAXN];
void addedge(int a,int b,int K){
    v[e]=b,next[e]=head[a],head[a]=e,cap[e]=K,e++;
    v[e]=a,next[e]=head[b],head[b]=e,cap[e]=0,e++;
}
bool BFS(int s,int t){
    int qf=0,qr,a,b,c;
    memset(dis,-1,sizeof(dis));
    q[qf++]=s,dis[s]=0;
    for(qr=0;qr<qf;){
        b=q[qr++];
        if(DBG)printf("BFS %d(%d)\n",b/2,b);
        for(a=head[b];a>=0;a=next[a]){
            if(DBG)printf("b flow %d %d\n",v[a],cap[a]);
            if(cap[a]&&dis[v[a]]<0){
                dis[v[a]]=dis[b]+1;
                if(DBG)printf("c %d dis %d\n",v[a]/2,dis[v[a]]);
                if(v[a]==t)return 1;
                q[qf++]=v[a];
            }
        }
    }
    return 0;
}
void dinic(){
    int a,b,c,f,s=2,t=2*N;
    while(BFS(s,t)){
        memcpy(work,head,sizeof(work));
        c=2,f=INF;
        while(1){
            if(DBG)printf("dinic %d\n",c);
            for(a=work[c];a>=0;a=next[a]){
                if(DBG)printf("a %d dis %d\n",v[a],dis[v[a]]);
                if(cap[a]&&dis[v[a]]==dis[c]+1){b=v[a];break;}
            }
            if(a>=0)work[c]=next[a];else work[c]=-1;
            if(a>=0){
                if(b==t){
                    if(DBG)printf("reach t\n");
                    f=min(f,cap[a]);
                    RES+=f,p[b]=c,pe[b]=a;
                    for(b=t;b!=s;b=p[b])cap[pe[b]]-=f,cap[pe[b]^1]+=f;
                    c=2,f=INF;
                }
                else{
                    p[b]=c,pe[b]=a,pf[b]=f;
                    f=min(f,cap[a]);
                    c=b;
                }
            }
            else{
                if(c==2)break;
                f=pf[c];
                c=p[c];
            }
        }
    }
}
void ans(){
    RES=0,dinic();
    printf("%d\n",RES);
}
int main(){
    int a,b,c,zn[MAXN];
    while(scanf("%d%d",&N,&M)==2){
        if(N+M==0)break;
        e=0,memset(head,-1,sizeof(head)),memset(zn,0,sizeof(zn));
        rep(i,N-2){scanf("%d%d",&a,&b);
            if(!b)zn[a]=1;
            else addedge(2*a,2*a+1,b);}
        rep(i,M){
            scanf("%d%d%d",&a,&b,&c);
            if(c&&!zn[a]&&!zn[b])addedge(2*a+1,2*b,c),addedge(2*b+1,2*a,c);}
        addedge(2,3,INF);
        ans();
    }
}

uva 10779 - Collector's Problem

Collector's Problem
Input: standard input
Output: standard output
Time Limit: 5 seconds

Some candy manufacturers put stickers into candy bar packages. Bob and his friends are collecting these stickers. They all want as many different stickers as possible, but when they buy a candy bar, they don't know which sticker is inside.
It happens that one person has duplicates of a certain sticker. Everyone trades duplicates for stickers he doesn't possess. Since all stickers have the same value, the exchange ratio is always 1:1.
But Bob is clever: he has realized that in some cases it is good for him to trade one of his duplicate stickers for a sticker he already possesses.
Now assume, Bob's friends will only exchange stickers with Bob, and they will give away only duplicate stickers in exchange with different stickers they don't possess.
Can you help Bob and tell him the maximum number of different stickers he can get by trading stickers with his friends?

Input

The first line of input contains the number of cases T (T<=20).
The first line of each case contains two integers n and m (2<=n<=10, 5<=m<=25). n is the number of people involved (including Bob), and m is the number of different stickers available.
The next n lines describe each person's stickers; the first of these lines describes Bob's stickers.
The i-th of these lines starts with a number ki<=50 indicating how many stickers person i has.
Then follows ki numbers between 1 and m indicating which stickers person i possesses.

Output

For each case, print the test case number together with the maximum number of different stickers Bob can get.

Sample Input

2
2 5
6 1 1 1 1 1 1
3 1 2 2
3 5
4 1 2 1 1
3 2 2 2
5 1 3 4 4 3
Sample Output
Case #1: 1
Case #2: 3
 
Explanation of the sample output:
In the first case, no exchange is possible, therefore Bob can have only the sticker with number 1.
In the second case, Bob can exchange a sticker with number 1 against a sticker with number 2 of the second person,
and then this sticker against a sticker with number 3 or 4 of the third person, and now he has stickers 1, 2 and 3 or 1, 2 and 4.

Problem setter: Adrian Kuegel

network flow,
A. 建模:
   1. source->每一個物品,容量為主角擁有物品的物量
   2. 每一個物品->其他朋友,容量為1,如果朋友沒有此物品的話
   3. 其他朋友->每一個物品,容量為n-1, 其中n為朋友擁有此物品之數量(>0時)
   4. 每一個物品->sink, 容量為1
B. 跑最大流
#include<stdio.h>
#include<cstring>
#include<string>
#include<vector>
#include<sstream>
#define REP(i, b, n) for (int i = b; i < n; i++)
#define rep(i,n) REP(i, 0, n)
#define DBG 0
#define INF int(1e18)
#define MAXN 40
#define MAXM 800
using namespace std;

int N,M,e=0,RES,cases=1;
int stks[10][25];
int v[MAXM],head[MAXN],cap[MAXM],next[MAXM],work[MAXN],p[MAXN],pe[MAXN],pf[MAXN],dis[MAXN];
int q[MAXN];
void addedge(int a,int b,int K){
v[e]=b,next[e]=head[a],head[a]=e,cap[e]=K,e++;
v[e]=a,next[e]=head[b],head[b]=e,cap[e]=0,e++;
}
bool BFS(){
int a,b,c,qr=0,qf=0;
q[qf++]=0;
memset(dis,-1,sizeof(dis));
dis[0]=0;
for(qr=0;qr<qf;){
b=q[qr++];
if(DBG)printf("BFS: %d\n",b);
for(a=head[b];a>=0;a=next[a]){
if(dis[v[a]]<0&&cap[a]){
dis[v[a]]=dis[b]+1;
if(DBG)printf("b: %d %d cap %d (%d)\n",v[a],dis[v[a]],cap[a],a);
if(v[a]==1)return 1;
q[qf++]=v[a];
}
}
}
return 0;
}
void dinic(){
int a,b,c,f;
while(BFS()){
c=0,f=INF;
memcpy(work,head,sizeof(head));
while(1){
if(DBG)printf("dinic %d %d\n",c,dis[c]);
for(a=work[c];a>=0;a=next[a]){
if(DBG)printf("b %d (%d)\n",v[a],dis[v[a]]);
if(cap[a]&&dis[v[a]]==dis[c]+1){b=v[a];break;}
}
if(a>=0)work[c]=next[a]; else work[c]=-1;
if(a>=0){
if(b==1){
if(DBG)printf("RES++\n");
pe[b]=a,p[b]=c,RES++;
for(;b!=0;b=p[b])cap[pe[b]]--,cap[pe[b]^1]++;
c=0,f=INF;
}
else{
pf[b]=f,p[b]=c,pe[b]=a;
f=min(f,cap[a]);
c=b;
}
}
else{
if(c==0)break;
f=pf[c];
c=p[c];
}
}
}
}
void ans(){
RES=0;
dinic();
printf("Case #%d: %d\n",cases++,RES);
}
void addNodes(){
rep(i,M){
if(DBG)printf("ae %d %d %d\n",0,i+1,stks[0][i]);
addedge(0,i+2,stks[0][i]);}
rep(i,M)rep(j,N-1){
if(!stks[j+1][i]){addedge(i+2,j+2+M,1);if(DBG)printf("ae %d %d %d\n",i+1,j+1,1);}
if(stks[j+1][i]>1){addedge(j+2+M,i+2,stks[j+1][i]-1);
if(DBG)printf("ae (%d %d) %d\n",j+1,1+i,stks[j+1][i]-1);}
}
rep(i,M)addedge(i+2,1,1);
}
int main(){
int n,a,b,c,cases=1;
stringstream buf;
char chs[200];
string s;
scanf("%d",&n);
rep(i,n){
scanf("%d%d ",&N,&M);
e=0,memset(head,-1,sizeof(head)),memset(stks,0,sizeof(stks));
rep(i,N){
fgets(chs,200,stdin);
if(chs[strlen(chs)-1]=='\n')chs[strlen(chs)-1]='\0';
buf.clear(),buf.str(chs),buf>>a;
rep(j,a)buf>>b,b--,stks[i][b]++;
}
addNodes();
ans();
}
}

2012年10月4日 星期四

uva 10330 - Power Transmission



 Power Transmission 


The Problem

DESA is taking a new project to transfer power. Power is generated by the newly established plant in Barisal. The main aim of this project is to transfer Power in Dhaka. As Dhaka is a megacity with almost 10 million people DESA wants to transfer maximum amount of power through the network. But as always occurs in case of power transmission it is tough to resist loss. So they want to use some regulators whose main aim are to divert power through several outlets without any loss.
Each such regulator has different capacity. It means if a regulator gets 100 unit power and it's capacity is 80 unit then remaining 20 unit power will be lost. Moreover each unidirectional link( Connectors among regulators) has a certain capacity. A link with capacity 20 unit cannot transfer power more than 20 unit. Each regulator can distribute the input power among the outgoing links so that no link capacity is overflown. DESA wants to know the maximum amount of power which can be transmitted throughout the network so that no power loss occurs. That is the job you have to do.

( Do not try to mix the above description with the real power transmission.)

The Input

The input will start with a postive integer N ( 1<=N<=100 ) indicates the number of regulators. The next few lines contain N positive integers indicating the capacity of each regulator from 1 to N. The next line contains another positive integer M which is the number of links available among the regulators. Following M lines contain 3 positive integers ( i j C) each. 'i' and 'j' is the regulator index ( 1<=i,j<=N) and C is the capacity of the link. Power can transfer from i'th regulator to j'th regulator. The next line contains another two positive integers B and D. B is the number of regulators which are the entry point of the network. Power generated in Barisal must enter in the network through these entry points. Simmilarly D is the number of regulators connected to Dhaka. These links are special and have infinite capacity. Next line will contain B+D integers each of which is an index of regulator. The first B integers are the index of regulators connected with Barisal. Regulators connected with Barisal are not connected with Dhaka.
Input is terminated by EOF.

The Output

For each test case show the maximum amount of power which can be transferred to Dhaka from Barisal. Use a seperate line for each test case.

Sample Input


4
10 20 30 40
6
1 2 5
1 3 10
1 4 13
2 3 5
2 4 7
3 4 20
3 1
1 2 3 4
2
50 100
1
1 2 100
1 1
1 2

Sample Output


37
50

Md. Kamruzzaman

network flow, dinic + 拆點
#include<stdio.h>
#include<cstring>
#include<algorithm>
#define REP(i, b, n) for (int i = b; i < n; i++)
#define rep(i,n) REP(i, 0, n)
#define DBG 0
#define INF int(1e9)
#define MAXN 210
#define MAXM 40000
using namespace std;

int N,M,SN,ON,cases=1,e;
long long RES;
int head[MAXN],v[MAXM],next[MAXM],cap[MAXM],
q[MAXN],p[MAXN],pe[MAXN],dis[MAXN],pf[MAXN],work[MAXM],eg[MAXM][3];
int ca[MAXN],sp[MAXN],op[MAXN];
bool trav[MAXN];
void addedge(int a,int b,int K){
if(DBG)printf("addedge(%d): %d %d\n",e,a,b);
v[e]=b,cap[e]=K,
next[e]=head[a],head[a]=e++;
v[e]=a,cap[e]=0,
next[e]=head[b],head[b]=e++;
}
int BFS(){
int a,b,c,i,rear=0;
memset(dis,-1,sizeof(dis));
q[0]=0;
dis[rear++]=0;
for(i=0;i<rear;i++){
b=q[i];
if(DBG)printf("BFS %d\n",b/2);
for(a=head[b];a>=0;a=next[a]){
if(dis[v[a]]<0&&cap[a]){
if(DBG)printf("c %d\n",v[a]/2);
dis[v[a]]=dis[b]+1;
if(v[a]==1){
if(DBG)printf("reach t: %d\n",dis[1]);
return dis[v[a]];
}
q[rear++]=v[a];
}
}
}
return INF;
}
void dinic(){
int a,b,c,f;
while(BFS()<INF){
int c=0;
memset(trav,0,sizeof(trav));
memcpy(work,head,sizeof(work)),f=INF;
while(1){
if(DBG)printf("DFS c %d\n",c/2);
for(a=work[c];a>=0;a=next[a]){
b=v[a];
if(cap[a]&&!trav[b]&&dis[b]==dis[c]+1)break;
}
work[c]=a;
if(a>=0){
if(b==1){
RES+=f;
p[b]=c,pe[b]=a;
if(DBG)printf("dreach t flow %d\n",f);
for(b=p[1];b!=0;b=p[b])cap[pe[b]]-=f,cap[pe[b]^1]+=f;
c=0,f=INF; //back to root
}
else{
if(DBG)printf("b f %d %d\n",b/2,f);
trav[b]=1,pf[b]=f;
p[b]=c,pe[b]=a;
f=min(f,cap[a]);
c=b;
}
}
else{
if(c==0)break;
f=pf[c];
c=p[c];
}
}
}
}
void ans(){
RES=0;
dinic();
printf("%lld\n",RES);
}
void addNodes(){
int a,b,c,d;
REP(i,1,N+1)addedge(2*i,2*i^1,ca[i-1]);
rep(i,SN)b=sp[i],addedge(0,2*b,INF);
rep(i,ON)b=op[i],addedge(2*b^1,1,1);
rep(i,M)b=eg[i][0],c=eg[i][1],addedge(2*b^1,2*c,eg[i][2]);
}
int main(){
int a,b,n,cases=1;
while(scanf("%d",&N)==1){
memset(head,-1,sizeof(head)),e=0;
rep(i,N)scanf("%d",&ca[i]);
scanf("%d",&M);
rep(i,M)scanf("%d%d%d",&eg[i][0],&eg[i][1],&eg[i][2]);
scanf("%d%d",&SN,&ON);
rep(i,SN)scanf("%d",&sp[i]);
rep(i,ON)scanf("%d",&op[i]);
if(DBG)printf("Case %d\n",cases++);
addNodes();
ans();
}
}

uva 563 - Crimewave



  Crimewave 

Nieuw Knollendam is a very modern town. This becomes clear already when looking at the layout of its map, which is just a rectangular grid of streets and avenues. Being an important trade centre, Nieuw Knollendam also has a lot of banks. Almost on every crossing a bank is found (although there are never two banks at the same crossing). Unfortunately this has attracted a lot of criminals. Bank hold-ups are quite common, and often on one day several banks are robbed. This has grown into a problem, not only to the banks, but to the criminals as well. After robbing a bank the robber tries to leave the town as soon as possible, most of the times chased at high speed by the police. Sometimes two running criminals pass the same crossing, causing several risks: collisions, crowds of police at one place and a larger risk to be caught.


To prevent these unpleasant situations the robbers agreed to consult together. Every Saturday night they meet and make a schedule for the week to come: who is going to rob which bank on which day? For every day they try to plan the get-away routes, such that no two routes use the same crossing. Sometimes they do not succeed in planning the routes according to this condition, although they believe that such a planning should exist.


Given a grid of $(s \times a)$ and the crossings where the banks to be robbed are located, find out whether or not it is possible to plan a get-away route from every robbed bank to the city-bounds, without using a crossing more than once.

Input 

The first line of the input contains the number of problems p to be solved.
  • The first line of every problem contains the number s of streets ( $1 \le s \le 50$), followed by the number a of avenues ( $1 \le a \le 50$), followed by the number b ($b \ge 1$) of banks to be robbed.
  • Then b lines follow, each containing the location of a bank in the form of two numbers x (the number of the street) and y (the number of the avenue). Evidently $1 \le x \le s$ and $1 \le y \le a$.

Output 

The output file consists of p lines. Each line contains the text possible or not possible. If it is possible to plan non-crossing get-away routes, this line should contain the word: possible. If this is not possible, the line should contain the words not possible.

Sample Input 


2
6 6 10
4 1
3 2
4 2
5 2
3 4
4 4
5 4
3 6
4 6
5 6
5 5 5
3 2
2 3
3 3
4 3
3 4

Sample Output 


possible
not possible




Miguel A. Revilla
1998-03-10

network flow, 為確保每點只有一能通過一次,每一點拆為兩點,中間串一條流量為1的edge
#include<stdio.h>
#include<cstring>
#define REP(i, b, n) for (int i = b; i < n; i++)
#define rep(i,n) REP(i, 0, n)
#define DBG 0
#define INF int(1e9)
#define MAXN 5100
#define MAXM 35000
using namespace std;

int N,M,B,LD,T,cases=1,e=0;
int head[MAXN],v[MAXM],next[MAXM],cap[MAXM],
q[MAXN],p[MAXN],pe[MAXN],dis[MAXN],dir[2][2],u[MAXN],work[MAXM];
int bks[MAXN][2];
bool trav[MAXN];
void addedge(int a,int b,int K){
if(DBG)printf("addedge(%d): %d %d\n",e,a,b);
v[e]=b,cap[e]=K,
next[e]=head[a],head[a]=e++;
v[e]=a,cap[e]=0,
next[e]=head[b],head[b]=e++;
}
int BFS(){
int a,b,c,t1,t2,i,rear=0;
memset(dis,-1,sizeof(dis));
q[0]=0;
dis[rear++]=0;
for(i=0;i<rear;i++){
if(DBG)printf("BFS %d(%d %d)\n",b,(b/2-1)%N+1,(b/2-1)/N+1);
for(a=head[q[i]];a>=0;a=next[a]){
if(dis[v[a]]<0&&cap[a]){
if(DBG)printf("c %d\n",c);
dis[v[a]]=dis[q[i]]+1;
if(v[a]==1){
if(DBG)printf("reach t: %d\n",dis[1]);
return dis[v[a]];
}
q[rear++]=v[a];
}
}
}
return INF;
}
void dinic(){
int a,b,c;
while(BFS()<INF){
int c=0;
memset(trav,0,sizeof(trav));
memcpy(work,head,sizeof(work));
while(1){
if(DBG)printf("DFS c %d\n",c);
for(a=work[c];a>=0;a=next[a]){
b=v[a];
if(cap[a]&&!trav[b]&&dis[b]==dis[c]+1)break;
}
work[c]=a;
if(a>=0){
if(b==1){
if(DBG)printf("reach t\n");
LD--;
p[b]=c,pe[b]=a;
for(b=1;b!=0;b=p[b])cap[pe[b]]-=1,cap[pe[b]^1]+=1;
c=0; //back to root
}
else{
trav[b]=1;
p[b]=c,pe[b]=a,c=b;
}
}
else{
if(c==0)break;
c=p[c];
}
}
}
}
void ans(){
LD=B;
dinic();
if(LD)printf("not possible\n");
else printf("possible\n");
}
int getNo(int x,int y){return x+y*N+1;}
bool valid(int a,int b){return a>=0&&a<N&&b>=0&&b<M;}
void addNodes(){
int a,b,c,d;
rep(j,M)rep(i,N)c=getNo(i,j),addedge(2*c,2*c^1,1);
if(DBG)printf("add nei\n");
rep(i,N)rep(j,M){ //neighbor and self
c=getNo(i,j);
rep(k,2){
a=i+dir[k][0],b=j+dir[k][1];
if(valid(a,b))d=getNo(a,b),addedge(2*c^1,d*2,1),addedge(2*d^1,2*c,1);
}
}
rep(i,B){
if(DBG)printf("bnk %d %d\n",bks[i][0]+1,bks[i][1]+1);
c=getNo(bks[i][0],bks[i][1]);
addedge(0,2*c,1);
}
int snk=1;
rep(i,N){
c=getNo(i,0),d=getNo(i,M-1);
addedge(2*c^1,snk,1),addedge(2*d^1,snk,1);
}
rep(i,M){
c=getNo(0,i),d=getNo(N-1,i);
addedge(2*c^1,snk,1),addedge(2*d^1,snk,1);
}
}
void init(){
dir[0][0]=1,dir[1][1]=1;
}
int main(){
int a,b,n;
scanf("%d",&n);
init();
rep(i,n)
while(scanf("%d%d%d",&N,&M,&B)==3){
memset(head,-1,sizeof(head)),e=0;
rep(i,B)scanf("%d%d",&bks[i][0],&bks[i][1]),bks[i][0]--,bks[i][1]--;
addNodes();
ans();
}
}

2012年10月3日 星期三

uva 10746 - Crime Wave – The Sequel


Problem G

Crime Wave – The Sequel

Input: Standard Input

Output: Standard Output
Time Limit: 2 Seconds

n banks have been robbed this fine day. m (greater than or equal to n) police cruisers are on duty at various locations in the city. n of the cruisers should be dispatched, one to each of the banks, so as to minimize the average time of arrival at the nbanks.

Input

The input file contains several sets of inputs. The description of each set is given below:
The first line of input contains 0 < n <= m <= 20. n lines follow, each containing m positive real numbers: the travel time for cruiser m to reach bank n.
Input is terminated by a case where m=n=0. This case should not be processed.  

Output

For each set of input output a single number: the minimum average travel time, accurate to 2 fractional digits.
 

Sample Input                             Output for Sample Input

3 4
10.0 23.0 30.0 40.0
5.0 20.0 10.0 60.0
18.0 20.0 20.0 30.0
0 0
13.33


Problemsetter: Gordon Cormack, EPS

二分圖最大匹配轉最小費用流 - 加上源點與匯點
注意浮點數誤差,加上epsilon(1e-8)以保證四捨五入
#include<stdio.h>
#include<cstring>
#include<queue>
#include<cmath>
#define REP(i, b, n) for (int i = b; i < n; i++)
#define rep(i,n) REP(i, 0, n)
#define DBG 0
#define INF (1e30)
#define MAXN 50
#define MAXM 900
#define eps 1e-8
using namespace std;

int N,M,D,K,LD,cases=1,e=0;
int head[MAXM],v[MAXM],next[MAXM],cap[MAXM],
cnt[MAXN],flow[MAXN],p[MAXN],pe[MAXN];
double RES,dis[MAXN],cost[MAXM];
bool trav[MAXN];

void addedge(int a,int b,int K,double w){
if(DBG)printf("addedge(%d): %d %d\n",e,a,b);
v[e]=b,cap[e]=K,cost[e]=w,
next[e]=head[a],head[a]=e++;
v[e]=a,cap[e]=0,cost[e]=-w,
next[e]=head[b],head[b]=e++;
}
bool relax(int u,int v,int e){
if(DBG)printf("enter relax(%d) u v cap cost dis[v] %d %d %d %f %f\n",e,u,v,cap[e],cost[e],dis[v]);
if(cap[e]&&dis[u]+cost[e]<dis[v]){
flow[v]=min(flow[u],cap[e]);
dis[v]=dis[u]+cost[e];
p[v]=u,pe[v]=e;
if(DBG)printf(" relax(%d): v cap dis %d %d %f\n",e,v,cap[v],dis[v]);
return 1;
}
return 0;
}
void SPFA(int s,int t){
int i,b,c,d,f;
double w;
queue<int>q;
rep(i,M+N+2)dis[i]=INF;
memset(trav,0,sizeof(trav));
memset(flow,0,sizeof(flow));
flow[0]=LD,dis[0]=0;
q.push(0);
while(q.size()){
c=q.front(),w=dis[c];q.pop();
if(DBG)printf("spfa v flow dis %d %d %f\n",c,flow[c],dis[c]);
trav[c]=0;
for(i=head[c];i!=-1;i=next[i]){
b=v[i];
if(relax(c,b,i)&&!trav[b]){
if(DBG)printf("b %d F %d\n",b,cap[i]);
trav[b]=1;
q.push(b);
}
}
}
f=flow[t];
LD-=f,RES+=f*dis[t];
if(DBG)printf("final LD cost dis: %d %d %f\n",LD,f,dis[t]);
for(b=t;b!=s;b=p[b]){if(DBG)printf("cut %d\n",pe[b]);cap[pe[b]]-=f,cap[pe[b]^1]+=f;}
}
void edmond(int s,int t){
while(LD){
if(DBG)printf("edm\n");
SPFA(s,t);
}
if(DBG)printf("dist: %d\n",RES);
}
void ans(){
RES=0,LD=N;
edmond(0,N+M+1);
printf("%.2f\n",RES/N+eps);
}
int main(){
int a,b,cases=1;
double c;
while(scanf("%d%d",&N,&M)==2){
if(N==0&&M==0)break;
if(DBG)printf("N M %d %d\n",N,M);
memset(head, -1, sizeof(head)),e=0;
rep(i,N){
rep(j,M)scanf("%lf",&c),addedge(j+1,i+M+1,1,c);
}
rep(i,N)addedge(i+M+1,N+M+1,1,0);
rep(i,M)addedge(0,i+1,1,0);
if(DBG)printf("cases %d\n",cases++);
ans();
}
}

2012年9月27日 星期四

uva 10480 - Sabotage



  Sabotage 

The regime of a small but wealthy dictatorship has been abruptly overthrown by an unexpected rebellion. Because of the enormous disturbances this is causing in world economy, an imperialist military super power has decided to invade the country and reinstall the old regime.
For this operation to be successful, communication between the capital and the largest city must be completely cut. This is a difficult task, since all cities in the country are connected by a computer network using the Internet Protocol, which allows messages to take any path through the network. Because of this, the network must be completely split in two parts, with the capital in one part and the largest city in the other, and with no connections between the parts.
There are large differences in the costs of sabotaging different connections, since some are much more easy to get to than others.
Write a program that, given a network specification and the costs of sabotaging each connection, determines which connections to cut in order to separate the capital and the largest city to the lowest possible cost.

Input 

Input file contains several sets of input. The description of each set is given below.
The first line of each set has two integers, separated by a space: First one the number of cities, n in the network, which is at most 50. The second one is the total number of connections, m, at most 500.
The following m lines specify the connections. Each line has three parts separated by spaces: The first two are the cities tied together by that connection (numbers in the range 1 - n). Then follows the cost of cutting the connection (an integer in the range 1 to 40000000). Each pair of cites can appear at most once in this list.
Input is terminated by a case where values of n and m are zero. This case should not be processed. For every input set the capital is city number 1, and the largest city is number 2.

Output 

For each set of input you should produce several lines of output. The description of output for each set of input is given below:
The output for each set should be the pairs of cities (i.e. numbers) between which the connection should be cut (in any order), each pair on one line with the numbers separated by a space. If there is more than one solution, any one of them will do.
Print a blank line after the output for each set of input.

Sample Input 

5 8
1 4 30
1 3 70
5 3 20
4 3 5
4 5 15
5 2 10
3 2 25
2 4 50
5 8
1 4 30
1 3 70
5 3 20
4 3 5
4 5 15
5 2 10
3 2 25
2 4 50
0 0

Sample Output 

4 1
3 4
3 5
3 2

4 1
3 4
3 5
3 2



Problem setter: Jesper Larsson, Lund University, Sweden


Maximum Network Flow => Min Cut
#include<stdio.h>
#include<cstring>
#include<string>
#include<vector>
#define REP(i, b, n) for (int i = b; i < n; i++)
#define rep(i,n) REP(i, 0, n)
#define DBG 0
using namespace std;

int N;
int p[50],h[50],gap[50],wgt[50][50],C[50][50];
int pf[50];
bool trav[50];
vector<int>egs[50];
int isap(int s,int t){
memset(h,0,sizeof(h));
memset(p,0,sizeof(p));
memset(gap,0,sizeof(gap));
int f=(int)1e9,res=0;
p[s]=s,pf[s]=f;
int b,c=s,d;
while(1){
b=-1;
if(DBG)printf("isap %d %d\n",c+1,h[c]);
rep(i,egs[c].size()){
d=egs[c][i];
if(wgt[c][d]&&h[c]==h[d]+1){b=d;break;}
}
if(b==t){
f=min(wgt[c][b],f);
if(DBG)printf("reach dest, f %d\n",f);
res+=f;
for(;b!=s;b=c,c=p[c]){
wgt[c][b]-=f,wgt[b][c]+=f;
if(DBG)printf(" wgt[%d][%d]=%d\n",c+1,b+1,wgt[c][b]);
}
c=s,f=(int)1e9;
}
else if(b>=0){
if(DBG)printf("move to %d\n",b+1);
pf[b]=f,p[b]=c;
f=min(f,wgt[c][b]);
c=b;
}
else{
if(--gap[h[c]]==0)break;
++gap[++h[c]];
f=pf[c];
c=p[c];
}
}
if(DBG)printf("flow: %d\n",res);
return res;
}
void DFS(int c){
int b;
if(DBG)printf("dfs %d\n",c);
trav[c]=1;
rep(i,egs[c].size()){
b=egs[c][i];
if(trav[b])continue;
if(wgt[c][b])DFS(b);
}
}
void ans(){
int res=isap(0,1);
if(DBG)printf("N %d\n",N);
memset(trav,0,sizeof(trav));
DFS(0); //get min cut
if(res){
rep(i,N)
if(trav[i])
rep(j,egs[i].size()){
if(!trav[egs[i][j]])printf("%d %d\n",i+1,egs[i][j]+1);
}
}
printf("\n");
}
int main(){
int m,a,b,c;
while(scanf("%d%d",&N,&m)==2){
if(N+m==0)break;
memset(wgt,0,sizeof(wgt)),memset(C,0,sizeof(C));rep(i,50)egs[i].clear();
rep(i,m){
scanf("%d%d%d",&a,&b,&c),a--,b--;
egs[a].push_back(b),egs[b].push_back(a);
C[a][b]=C[b][a]=wgt[a][b]=wgt[b][a]=c;
}
ans();
}
}

uva 259 - Software Allocation



 Software Allocation 

A computing center has ten different computers (numbered 0 to 9) on which applications can run. The computers are not multi-tasking, so each machine can run only one application at any time. There are 26 applications, named A to Z. Whether an application can run on a particular computer can be found in a job description (see below).

Every morning, the users bring in their applications for that day. It is possible that two users bring in the same application; in that case two different, independent computers will be allocated for that application.

A clerk collects the applications, and for each different application he makes a list of computers on which the application could run. Then, he assigns each application to a computer. Remember: the computers are not multi-tasking, so each computer must handle at most one application in total. (An application takes a day to complete, so that sequencing i.e. one application after another on the same machine is not possible.)
A job description consists of

  1. one upper case letter A...Z, indicating the application.
  2. one digit 1...9, indicating the number of users who brought in the application.
  3. a blank (space character.)
  4. one or more different digits 0...9, indicating the computers on which the application can run.
  5. a terminating semicolon `;'.
  6. an end-of-line.

Input

The input for your program is a textfile. For each day it contains one or more job descriptions, separated by a line containing only the end-of-line marker. The input file ends with the standard end-of-file marker. For each day your program determines whether an allocation of applications to computers can be done, and if so, generates a possible allocation.

Output

The output is also a textfile. For each day it consists of one of the following:

  • ten characters from the set {`A'...`Z' , `_'}, indicating the applications allocated to computers 0 to 9 respectively if an allocation was possible. An underscore `_' means that no application is allocated to the corresponding computer.
  • a single character `!', if no allocation was possible.

Sample Input


A4 01234;
Q1 5;
P4 56789;

A4 01234;
Q1 5;
P5 56789;

Sample Output


AAAA_QPPPP
!


Maximum Network Flow 
#include<stdio.h>
#include<cstring>
#include<string>
#include<vector>
#define REP(i, b, n) for (int i = b; i < n; i++)
#define rep(i,n) REP(i, 0, n)
#define DBG 0
using namespace std;

int N,TSN;
vector<int>egs[50];
int wgt[50][50],p[50],pf[50],gap[50],h[50],PI[50];
int isap(int s,int t){
    int i,b,c=s,f=int(1e9),res=0;
    memset(gap,0,sizeof(gap));
    memset(h,0,sizeof(h));
    memset(p,0,sizeof(p));
    pf[s]=int(1e9), p[s]=s;
    if(DBG)printf("N %d\n",N);
    while(1){
        if(DBG)printf("isap %d f %d h %d\n",c,f,h[c]);
        b=-1;
        rep(i,egs[c].size()){
            int d=egs[c][i];
            //if(DBG)printf("wgt[%d][%d]=%d\n",c,b,wgt[c][b]);
            if(wgt[c][d]>0&&h[c]==h[d]+1){b=egs[c][i];break;}
        }
        if(b==t){
            f=min(f,wgt[c][b]);
            res+=f;
            if(DBG)printf("t: computer %d res %d\n",c-27,res);
            for(;b!=s;PI[b]=c,b=c,c=p[c]){
                wgt[c][b]-=f,wgt[b][c]+=f;
                if(DBG)printf("f %d wgt[%d][%d]=%d\n",f,c,b,wgt[c][b]);
            }
            c=s,f=int(1e9);
        }
        else if(b>=0){
            if(DBG)printf("move to %d, ",b);
            pf[b]=f;
            f=min(f,wgt[c][b]);
            if(DBG)printf("f %d\n",f);
            p[b]=c;
            c=b;
        }
        else{
            if(DBG)printf("raise %d: %d\n",c, h[c]+1);
            if(--gap[h[c]]==0)break;
            ++gap[++h[c]];
            f=pf[c];
            c=p[c];
        }
    }
    return res;
}
void ans(){
    memset(PI,0,sizeof(PI));
   int res=isap(0,49);
   if(res==TSN){rep(i,10)if(PI[i+27])printf("%c",PI[i+27]+'@');else printf("_");printf("\n");}
   else printf("!\n");
}
int main(){
    int cn,tn;
    char chs[100];
    N=12;
    while(fgets(chs,100,stdin)){
        if(chs[0]=='\n'){
            ans();
            TSN=0,N=12,memset(wgt,0,sizeof(wgt));rep(i,50)egs[i].clear();
            scanf(" ");
            continue;
        }
        N++;
        if(chs[strlen(chs)-1]=='\n')chs[strlen(chs)-1]='\0';
        tn=chs[0]-'@';
        egs[0].push_back(tn);
        wgt[0][tn]=chs[1]-'0';
        TSN+=wgt[0][tn];                //all tasks
        if(DBG)printf("task %d\n",tn);
        rep(i,10)egs[i+27].push_back(49);
        REP(i,3,strlen(chs)-1){
            cn=chs[i]-'0'+27;
            if(DBG)printf("  com %d\n",cn);
            egs[tn].push_back(cn),egs[cn].push_back(tn);
            wgt[tn][cn]=1,wgt[cn][49]=1;
        }
    }
    if(egs[0].size())ans();
}

2012年8月7日 星期二

uva 10249 - The Grand Dinner


Problem D
The Grand Dinner
Input: standard input
Output: standard output
Time Limit: 15 seconds
Memory Limit: 32 MB

Each team participating in this year’s ACM World Finals contest is expected to join the grand dinner to be arranged after the prize giving ceremony ends. In order to maximize the interaction among the members of different teams, it is expected that no two members of the same team sit at the same table.

Now, given the number of members in each team (including contestants, coaches, reserves, guests etc.) and the seating capacity of each available table, you are to determine whether it is possible for the teams to sit as described in the previous paragraph. If such an arrangement is possible you must also output one possible seating arrangement. If there are multiple possible arrangements, any one is acceptable.

Input
 The input file may contain multiple test cases. The first line of each test case contains two integers M (1 £ M £70) and N (1 £ N £ 50) denoting the number of teams and the number of tables respectively. The second line of the test case contains M integers where the i-th (1 £ i £ M) integer mi (1 £ mi £ 100) indicates the number of members of team i. The third line contains N integers where the j-th (1 £ j £ N) integer nj (2 £ nj £ 100)indicates the seating capacity of table j.

A test case containing two zeros for M and N terminates the input.

Output
For each test case in the input print a line containing either 1 or 0 depending on whether or not there exists a valid seating arrangement of the team members. In case of a successful arrangement print M additional lines where the i-th (1 £ i £ M) of these lines contains a table number (an integer from 1 to N) for each of the members of team i.

Sample Input
4 5
4 5 3 5
3 5 2 6 4
4 5
4 5 3 5
3 5 2 6 3
0 0


Sample Output
1
1 2 4 5
1 2 3 4 5
2 4 5
1 2 3 4 5
0

(World Finals Warm-up Contest, Problem Setter: Rezaul Alam Chowdhury)

network flow, ISAP
另有更快的貪心法解:  

2012年8月6日 星期一

uva 820 - Internet Bandwidth



  Internet Bandwidth 

On the Internet, machines (nodes) are richly interconnected, and many paths may exist between a given pair of nodes. The total message-carrying capacity (bandwidth) between two given nodes is the maximal amount of data per unit time that can be transmitted from one node to the other. Using a technique called packet switching, this data can be transmitted along several paths at the same time.
For example, the following figure shows a network with four nodes (shown as circles), with a total of five connections among them. Every connection is labeled with a bandwidth that represents its data-carrying capacity per unit time.
In our example, the bandwidth between node 1 and node 4 is 25, which might be thought of as the sum of the bandwidths 10 along the path 1-2-4, 10 along the path 1-3-4, and 5 along the path 1-2-3-4. No other combination of paths between nodes 1 and 4 provides a larger bandwidth.
You must write a program that computes the bandwidth between two given nodes in a network, given the individual bandwidths of all the connections in the network. In this problem, assume that the bandwidth of a connection is always the same in both directions (which is not necessarily true in the real world).

Input 

The input file contains descriptions of several networks. Every description starts with a line containing a single integer n (2 ≤n ≤100), which is the number of nodes in the network. The nodes are numbered from 1 to n. The next line contains three numbers s, t, and c. The numbers s and t are the source and destination nodes, and the number c is the total number of connections in the network. Following this are c lines describing the connections. Each of these lines contains three integers: the first two are the numbers of the connected nodes, and the third number is the bandwidth of the connection. The bandwidth is a non-negative number not greater than 1000.
There might be more than one connection between a pair of nodes, but a node cannot be connected to itself. All connections are bi-directional, i.e. data can be transmitted in both directions along a connection, but the sum of the amount of data transmitted in both directions must be less than the bandwidth.
A line containing the number 0 follows the last network description, and terminates the input.

Output 

For each network description, first print the number of the network. Then print the total bandwidth between the source node s and the destination node t, following the format of the sample output. Print a blank line after each test case.

Sample InputOutput for the Sample Input
4
1 4 5
1 2 20
1 3 10
2 3 5
2 4 10
3 4 20
0
Network 1
The bandwidth is 25.


ACM World Finals 2000, Problem E

network flow, ISAP