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年9月26日 星期三

uva 11838 - Come and Go



  Come and Go 

In a certain city there are N intersections connected by one-way and two-way streets. It is a modern city, and several of the streets have tunnels or overpasses. Evidently it must be possible to travel between any two intersections. More precisely given two intersections V and W it must be possible to travel from V to W and from W to V.Your task is to write a program that reads a description of the city street system and determines whether the requirement of connectedness is satisfied or not.

Input 

The input contains several test cases. The first line of a test case contains two integers N and M, separated by a space, indicating the number of intersections ( 2$ \le$N$ \le$2000) and number of streets ( 2$ \le$M$ \le$N(N - 1)/2). The next M lines describe the city street system, with each line describing one street. A street description consists of three integers VW andP, separated by a blank space, where V and W are distinct identifiers for intersections (1$ \le$VW$ \le$NV$ \ne$W ) and P can be 1 or 2; if P = 1 the street is one-way, and traffic goes from V to W; if P = 2 then the street is two-way and links V and W. A pair of intersections is connected by at most one street.The last test case is followed by a line that contains only two zero numbers separated by a blank space.

Output 

For each test case your program should print a single line containing an integer G, where G is equal to one if the condition of connectedness is satisfied, and G is zero otherwise.

Sample Input 


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

Sample Output 


1
1
0
0



Graph, SCC (Strong Connected Component)

#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,low[2000],q[2000],scnt,cp,cnt,rnum;
vector<int>egs[2000];
bool trav[2000];
void tarjan(int a){
    if(DBG)printf("scc %d eg %d\n",a,egs[a].size());
    int b,c,m;
    trav[a]=1,m=low[a]=cnt++;
    q[cp++]=a;
    rep(i,egs[a].size()){
        b=egs[a][i];
        if(!trav[b])tarjan(b);
        if(low[b]<m)m=low[b];
    }
    if(m<low[a]){low[a]=m;return;}
    if(DBG)printf("found scc %d m %d low[%d] %d\n",a,m,a,low[a]);
    rnum=cp;
    do{
        low[c=q[--cp]]=N;
    }while(c!=a);
    scnt++;
}
void ans(){
    scnt=cp=cnt=0;
    memset(trav,0,sizeof(trav));
    tarjan(0);
    if(scnt==1&&rnum==N)printf("1\n");
    else printf("0\n");
}
int main(){
    int a,b,c,m,n;
    while(scanf("%d%d",&N,&m)==2){
        if(N+m==0)break;
        rep(i,2000)egs[i].clear();
        rep(i,m){
            scanf("%d%d%d",&a,&b,&c);
            if(DBG)printf("a b c %d %d %d\n",a,b,c);
            a--,b--;
            if(c==2)egs[a].push_back(b),egs[b].push_back(a);
            else egs[a].push_back(b);
            if(DBG)printf("egs[%d]: %d\n",a,egs[a].size());
        }
        ans();
    }
}

uva 11504 - Dominos


Problem D: Dominos

Dominos are lots of fun. Children like to stand the tiles on their side in long lines. When one domino falls, it knocks down the next one, which knocks down the one after that, all the way down the line. However, sometimes a domino fails to knock the next one down. In that case, we have to knock it down by hand to get the dominos falling again.Your task is to determine, given the layout of some domino tiles, the minimum number of dominos that must be knocked down by hand in order for all of the dominos to fall.

Input Specification

The first line of input contains one integer specifying the number of test cases to follow. Each test case begins with a line containing two integers, each no larger than 100 000. The first integer n is the number of domino tiles and the second integer m is the number of lines to follow in the test case. The domino tiles are numbered from 1 to n. Each of the following lines contains two integers x and y indicating that if domino number x falls, it will cause domino number y to fall as well.

Sample Input

1
3 2
1 2
2 3

Output Specification

For each test case, output a line containing one integer, the minimum number of dominos that must be knocked over by hand in order for all the dominos to fall.

Output for Sample Input

1

Ondřej Lhoták

Graph, Strong Connected Component
note: use Tarjan will cause Runtime Error due to recursive stack overflow!!T.T
use Kosaraju algorithm instead

#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,low[100000],q[100000],in[100000],id[100000],scnt,cp,cnt;
vector<int>egs[100000],regs[100000],finish;
bool trav[100000];
/*void tarjan(int a){
    if(DBG)printf("scc %d\n",a);
    int b,c,m;
    trav[a]=1,m=low[a]=cnt++;
    q[cp++]=a;
    rep(i,egs[a].size()){
        b=egs[a][i];
        if(!trav[b])scc(b);
        if(low[b]<m)m=low[b];
    }
    if(m<low[a]){low[a]=m;return;}
    //if(DBG)printf("found scc %d m %d low[%d] %d\n",a,m,a,low[a]);
    do{
        id[c=q[--cp]]=scnt,low[c]=N;
    }while(c!=a);
    scnt++;
    //if(DBG)printf("scnt: %d\n",scnt);
}*/
void DFS(int cur){
    if(trav[cur])return;
    trav[cur]=1;
    rep(i,egs[cur].size())DFS(egs[cur][i]);
    finish.push_back(cur);
}
void DFS2(int a,int b){
    if(trav[a])return;
    trav[a]=1,id[a]=b;
    rep(i,regs[a].size())if(!trav[regs[a][i]])DFS2(regs[a][i],b);
}
void kosaraju(){
    int b;
    memset(trav,0,sizeof(trav));
    rep(i,N)DFS(i);
    memset(trav,0,sizeof(trav));
    rep(i,N){
        b=finish[N-1-i];
        if(!trav[b]){
            if(DBG)printf("find scc %d\n",b);
            DFS2(b,scnt++);
        }
    }
}
void ans(){
    int tot=0,b;
    finish.clear();
    memset(trav,0,sizeof(trav));
    memset(id,-1,sizeof(id));
    memset(in,0,sizeof(in));
    cp=cnt=scnt=0;
    kosaraju();             //find all scc
    rep(i,N)rep(j,egs[i].size()){
        b=egs[i][j];
        if(id[i]!=id[b]){
            in[id[b]]++;
        }
    }
    rep(i,scnt)if(!in[i])tot++;
    printf("%d\n",tot);
}
int main(){
    int a,b,m,n;
    scanf("%d",&n);
    rep(i,n){
        scanf("%d%d",&N,&m);
        rep(i,N)egs[i].clear(),regs[i].clear();
        rep(i,m){
            scanf("%d%d",&a,&b),a--,b--;
            if(a!=b)regs[b].push_back(a),egs[a].push_back(b);
        }
        ans();
    }
}


uva 247 - Calling Circles



 Calling Circles 

If you've seen television commercials for long-distance phone companies lately, you've noticed that many companies have been spending a lot of money trying to convince people that they provide the best service at the lowest cost. One company has ``calling circles." You provide a list of people that you call most frequently. If you call someone in your calling circle (who is also a customer of the same company), you get bigger discounts than if you call outside your circle. Another company points out that you only get the big discounts for people in your calling circle, and if you change who you call most frequently, it's up to you to add them to your calling circle.

LibertyBell Phone Co. is a new company that thinks they have the calling plan that can put other companies out of business. LibertyBell has calling circles, but they figure out your calling circle for you. This is how it works. LibertyBell keeps track of all phone calls. In addition to yourself, your calling circle consists of all people whom you call and who call you, either directly or indirectly.
For example, if Ben calls Alexander, Alexander calls Dolly, and Dolly calls Ben, they are all within the same circle. If Dolly also calls Benedict and Benedict calls Dolly, then Benedict is in the same calling circle as Dolly, Ben, and Alexander. Finally, if Alexander calls Aaron but Aaron doesn't call Alexander, Ben, Dolly, or Benedict, then Aaron is not in the circle.

You've been hired by LibertyBell to write the program to determine calling circles given a log of phone calls between people.

Input

The input file will contain one or more data sets. Each data set begins with a line containing two integers, n and m. The first integer, n, represents the number of different people who are in the data set. The maximum value for n is 25. The remainder of the data set consists of m lines, each representing a phone call. Each call is represented by two names, separated by a single space. Names are first names only (unique within a data set), are case sensitive, and consist of only alphabetic characters; no name is longer than 25 letters.
For example, if Ben called Dolly, it would be represented in the data file as

Ben Dolly
Input is terminated by values of zero (0) for n and m.

Output

For each input set, print a header line with the data set number, followed by a line for each calling circle in that data set. Each calling circle line contains the names of all the people in any order within the circle, separated by comma-space (a comma followed by a space). Output sets are separated by blank lines.

Sample Input


5 6
Ben Alexander
Alexander Dolly
Dolly Ben
Dolly Benedict
Benedict Dolly
Alexander Aaron
14 34
John Aaron
Aaron Benedict
Betsy John
Betsy Ringo
Ringo Dolly
Benedict Paul
John Betsy
John Aaron
Benedict George
Dolly Ringo
Paul Martha
George Ben
Alexander George
Betsy Ringo
Alexander Stephen
Martha Stephen
Benedict Alexander
Stephen Paul
Betsy Ringo
Quincy Martha
Ben Patrick
Betsy Ringo
Patrick Stephen
Paul Alexander
Patrick Ben
Stephen Quincy
Ringo Betsy
Betsy Benedict
Betsy Benedict
Betsy Benedict
Betsy Benedict
Betsy Benedict
Betsy Benedict
Quincy Martha
0 0

Sample Output


Calling circles for data set 1:
Ben, Alexander, Dolly, Benedict
Aaron

Calling circles for data set 2:
John, Betsy, Ringo, Dolly
Aaron
Benedict
Paul, George, Martha, Ben, Alexander, Stephen, Quincy, Patrick


Graph, SCC (strong connected component)
#include<stdio.h>
#include<cstring>
#include<string>
#include<vector>
#include<map>
#define REP(i, b, n) for (int i = b; i < n; i++)
#define rep(i,n) REP(i, 0, n)
#define DBG 1
using namespace std;

int N,low[25],scnt,cases=1,cp,cnt,q[25];
vector<int>egs[25],gp[25];
map<string,int>mp;
vector<string>name;
bool trav[100],eg[25][25];
void scc(int a){
if(DBG)printf("scc %d\n",a);
int b,c,m;
trav[a]=1,m=low[a]=cnt++;
q[cp++]=a;
rep(i,egs[a].size()){
b=egs[a][i];
if(!trav[b])scc(b);
if(low[b]<m)m=low[b];
}
if(m<low[a]){low[a]=m;return ;}
if(DBG)printf("found scc %d m %d low[%d] %d\n",a,m,a,low[a]);
do{
gp[scnt].push_back(c=q[--cp]),low[c]=N;
}while(c!=a);
scnt++;
}
void ans(){
memset(low,0,sizeof(low));
memset(trav,0,sizeof(trav));
cnt=0,scnt=0,cp=0;
rep(i,N)if(!trav[i])scc(i);
printf("Calling circles for data set %d:\n",cases++);
rep(i,scnt){
bool ll=0;
rep(j,gp[i].size()){if(ll)printf(", ");ll=1;printf("%s",name[gp[i][j]].c_str());}
printf("\n");
}
}
int main(){
char chs[40],chs2[40];
int a,b,m,n;
bool ll=0;
while(scanf("%d%d",&N,&m)==2){
if(N+m==0)break;
rep(i,25)egs[i].clear(),gp[i].clear();
name.clear(),mp.clear(),n=0,memset(eg,0,sizeof(eg));
rep(i,m){scanf("%s%s",chs,chs2);
if(!mp.count(chs))mp[chs]=n++,name.push_back(chs);
if(!mp.count(chs2))mp[chs2]=n++,name.push_back(chs2);
a=mp[chs],b=mp[chs2];
if(!eg[a][b])egs[a].push_back(b),eg[a][b]=1;
}
if(ll)printf("\n");ll=1;
ans();
}
}

uva 10199 - Tourist Guide



 Problem F: Tourist Guide 


The Problem

Rio de Janeiro is a very beautiful city. But there are so many places to visit that sometimes you feel a bit lost. But don't worry, because your friend Bruno promised you to be your tourist guide. The problem is that he is not a very good driver, as he can't see very well (poor Bruno).
Because of his disabilities, Bruno have a lot of fines to pay and he doesn't want to have even more to pay, even though he promised you to be your tourist guide. What he would like to know, however, is where are all the cameras that help the police to fine the bad drivers, so he can drive more carefully when passing by them.
Those cameras are strategically distributed over the city, in locations that a driver must pass through in order to go from one zone of the city to another. In order words, if there are two city locations A and B such that to go from one to another (A to B or B to A) a driver must pass through a location C, then C will have a camera.
For instance, suppose that we have 6 locations (A, B, C, D, E and F) and that we have 7 routes (all of them bidirectonal) B-C, A-B, C-A, D-C, D-E, E-F and F-C. There's a camera on C because to go from A to E, for instance, you must pass through C. In this configuration, there's only one camera (on C).
Your task is to help Bruno (as he wants to be a musician and he doesn't want to get even close of computers) and write a program which will tell him where are all the cameras, given the map of the city, so he can be your tourist guide and avoid further fines.

The Input

The input will consist on an arbitrary number of city maps. Each city map will begin with an integer N (2 < N <= 100) which stands for the total locations of the city. Then will follow N different place names, one per line. Each place name will have at least one and at most 30 characters (all of them will be lowercase latin letters). Then will follow a non-negative integer R which stands for the total routes of the city. Then will follow R lines with the routes. Each route will be represented by the name of both places that the route connects (remember that the routes are bidirectional). Location names in route description will always be valid and there will be no route from one place to itself. You must read until N = 0, and this input should not be processed.

The Output

For each city map you must print the line:
City map #d: c camera(s) found
Where d stands for the city map number (starting from 1) and c stands for the total number of cameras. Then should follow c lines with the location names where are each camera (in alphabetic order). You should print a blank line between output sets.

Sample Input


6
sugarloaf
maracana
copacabana
ipanema
corcovado
lapa
7
ipanema copacabana
copacabana sugarloaf
ipanema sugarloaf
maracana lapa
sugarloaf maracana
corcovado sugarloaf
lapa corcovado
5
guanabarabay
downtown
botanicgarden
colombo
sambodromo
4
guanabarabay sambodromo
downtown sambodromo
sambodromo botanicgarden
colombo sambodromo
0

Sample Output


City map #1: 1 camera(s) found
sugarloaf

City map #2: 1 camera(s) found
sambodromo

© 2001 Universidade do Brasil (UFRJ). Internal Contest 2001.

Articulation point
#include<stdio.h>
#include<cstring>
#include<string>
#include<vector>
#include<algorithm>
#include<map>
#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,lbl[100],num,cases=1,parent[100];
vector<int>egs[100];
map<string,int>mp;
vector<string>name;
bool trav[100],arti[100];
void find(int root, int a){
if(DBG)printf("find %d parent %d\n",a,parent[a]);
int b,child=0,m=101;
bool ap=0;
lbl[a]=num++,trav[a]=1;
rep(i,egs[a].size()){
b=egs[a][i];
if(!trav[b]){
child++;
parent[b]=lbl[a],find(root,b);
if(parent[b]>=lbl[a])ap=1;
m=min(parent[b],m);
}
else if(lbl[b]<parent[a]){
if(DBG)printf("find old %d\n",b);
parent[a]=lbl[b];
}
}
if(DBG)printf("a m %d %d\n",a,m);
if(m<parent[a])parent[a]=m;
if(a==root&&child>1||a!=root&&ap){if(DBG)printf("arti: %d\n",a);arti[a]=1;}
}
void ans(){
vector<string>res;
memset(parent,0,sizeof(parent));
memset(arti,0,sizeof(arti));
memset(trav,0,sizeof(trav));
num=0;
int tot=0;
rep(i,N)if(!trav[i])find(i,i);
rep(i,N)if(arti[i])tot++,res.push_back(name[i]);
printf("City map #%d: %d camera(s) found\n",cases++,tot);
if(name.size()){
sort(res.begin(),res.end());
rep(i,res.size())printf("%s\n",res[i].c_str());
}
}
int main(){
char chs[40],chs2[40];
int a,b,m,n=0;
bool ll=0;
while(scanf("%d",&N)==1){
if(N==0)break;
n=0,name.clear(),mp.clear();
rep(i,100)egs[i].clear();
rep(i,N)scanf("%s",chs),mp[chs]=n++,name.push_back(chs);
scanf("%d",&m);
rep(i,m){scanf("%s%s",chs,chs2),a=mp[chs],b=mp[chs2],
egs[a].push_back(b),egs[b].push_back(a);if(DBG)printf("%d-%d\n",a,b);}
if(ll)printf("\n");ll=1;
ans();
}
}

uva 11396 - Claw Decomposition


Problem B
Claw Decomposition
Input: Standard Input
Output: Standard Output

A claw is defined as a pointed curved nail on the end of each toe in birds, some reptiles, and some mammals. However, if you are a graph theory enthusiast, you may understand the following special class of graph as shown in the following figure by the word claw.
If you are more concerned about graph theory terminology, you may want to define claw as K1,3.

Let’s leave the definition for the moment & come to the problem. You are given a simple undirected graph in which every vertex has degree 3. You are to figure out whether the graph can be decomposed into claws or not.

Just for the sake of clarity, a decomposition of a graph is a list of subgraphs such that each edge appears in exactly one subgraph in the list.

Input

There will be several cases in the input file. Each case starts with the number of vertices in the graph, V (4<=V<=300). This is followed by a list of edges. Every line in the list has two integers, a & b, the endpoints of an edge (1<=a,b<=V). The edge list ends with a line with a pair of 0. The end of input is denoted by a case with V=0. This case should not be processed.

Output

For every case in the input, print YES if the graph can be decomposed into claws & NO otherwise.

Sample Input                                                  Output for Sample Input
4
1 2
1 3
1 4
2 3
2 4
3 4
0 0
6
1 2
1 3
1 6
2 3
2 5
3 4
4 5
4 6
5 6
0 0
0
NO
NO



Problemsetter: Mohammad Mahmudur Rahman
Special Thanks to: Manzurur Rahman Khan

Graph, Bipartite checking
<br/>#include&lt;stdio.h&gt;<br/>#include&lt;cstring&gt;<br/>#include&lt;string&gt;<br/>#include&lt;vector&gt;<br/>#define REP(i, b, n) for (int i = b; i &lt; n; i++)<br/>#define rep(i,n) REP(i, 0, n)<br/>#define DBG 0<br/>using namespace std;<br/><br/>int N,color[300];<br/>vector&lt;int&gt;egs[300];<br/>bool trav[300];<br/>bool mark(int u,int cr){<br/>    int b;<br/>    if(DBG)printf(&quot;mark %d %d\n&quot;,u,cr);<br/>    trav[u]=1,color[u]=cr;<br/>    int nc=(cr==1?2:1);<br/>    rep(i,egs[u].size()){<br/>        b=egs[u][i];<br/>        if(color[b]&amp;&amp;color[b]!=nc)return 0;         //traverse and wrong color<br/>        if(!trav[b])mark(b,nc);<br/>    }<br/>    return 1;<br/>}<br/>void ans(){<br/>    bool fail=0;<br/>    memset(color,0,sizeof(color));<br/>    memset(trav,0,sizeof(trav));<br/>    rep(i,N){<br/>        if(!trav[i]){<br/>            if(!mark(i,1)){fail=1;break;}<br/>        }<br/>    }<br/>    if(!fail)printf(&quot;YES\n&quot;);<br/>    else printf(&quot;NO\n&quot;);<br/>}<br/>int main(){<br/>    int a,b;<br/>    while(scanf(&quot;%d&quot;,&amp;N)==1){<br/>        rep(i,300)egs[i].clear();<br/>        if(N==0)break;<br/>        while(scanf(&quot;%d%d&quot;,&amp;a,&amp;b)==2){<br/>            if(a+b==0)break;<br/>            else a--,b--,egs[a].push_back(b),egs[b].push_back(a);<br/>        }<br/>        ans();<br/>    }<br/>}<br/>

11080 - Place the Guards


Problem G
Place the Guards
Input: Standard Input
Output: Standard Output
In the country of Ajabdesh there are some streets and junctions. Each street connects 2 junctions. The king of Ajabdesh wants to place some guards in some junctions so that all the junctions and streets can be guarded by them. A guard in a junction can guard all the junctions and streets adjacent to it. But the guards themselves are not gentle. If a street is guarded by multiple guards then they start fighting. So the king does not want the scenario where a street may be guarded by two guards. Given the information about the streets and junctions of Ajabdesh, help the king to find the minimum number of guards needed to guard all the junctions and streets of his country.
           
Input:
The first line of the input contains a single integer T (T<80 2="2" begins="begins" case="case" cases.="cases." class="GramE" each="each" indicating="indicating" nbsp="nbsp" number="number" of="of" span="span" test="test" the="the" with="with">integers
 v (1 ≤ ≤ 200) and e (0 ≤ ≤ 10000.). v is the number of junctions and e is the number of streets. Each of the next e line contains 2 integer f and t denoting that there is a street between f and t. All the junctions are numbered from 0 to v-1.

Output:
For each test case output in a single line an integer m denoting the minimum number of guards needed to guard all the junctions and streets. Set the value of m as -1 if it is impossible to place the guards without fighting.

Sample Input                             Output for Sample Input

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


Problemsetter: Abdullah-al-Mahmud
Special Thanks: Md. Kamruzzaman

Graph, Bipartite checking

#include<stdio.h>
#include<cstring>
#include<string>
#include<algorithm>
#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,E,color[200],cn;
vector<int>egs[200];
bool trav[200];
bool mark(int u,int cr,int &len){
int b;
if(DBG)printf("mark %d %d\n",u,cr);
trav[u]=1,color[u]=cr;
if(cr==1)cn++;
int nc=(cr==1?2:1);
rep(i,egs[u].size()){
b=egs[u][i];
if(color[b]&&color[b]!=nc)return 0; //traverse and wrong color
if(!trav[b])len++,mark(b,nc,len);
}
return 1;
}
void ans(){
int tot=0,len,c;
bool fail=0;
memset(color,0,sizeof(color));
memset(trav,0,sizeof(trav));
rep(i,N){
if(!trav[i]){
cn=0,len=1;
if(mark(i,1,len)){
if(DBG)printf("len cn %d %d\n",len,cn);
c=min(cn,len-cn);
if(c==0)c=1;
tot+=c;
}
else {fail=1;break;}
}
}
if(!fail)printf("%d\n",tot);
else printf("-1\n");
}
int main(){
int n,m,a,b;
scanf("%d",&n);
rep(i,n){
rep(i,200)egs[i].clear();
E=0;
scanf("%d%d",&N,&m);
rep(i,m)scanf("%d%d",&a,&b),egs[a].push_back(b),egs[b].push_back(a),E++;
ans();
}
}

2012年9月25日 星期二

uva 11060 - Beverages


Problem E - Beverages

Time Limit: 1 second


Dilbert has just finished college and decided to go out with friends. Dilbert has some strange habits and thus he decided to celebrate this important moment of his life drinking a lot. He will start drinking beverages with low alcohol content, like beer, and then will move to a beverage that contains more alcohol, like wine, until there are no more available beverages. Once Dilbert starts to drink wine he will not drink beer again, so the alcohol content of the beverages never decreases with the time.
You should help Dilbert by indicating an order in which he can drink the beverages in the way he wishes.

Input

Each test case starts with 1 ≤ N ≤ 100, the number of available beverages. Then will follow N lines, informing the name of each beverage, a name has less than 51 characters and has no white spaces. Then there is another line with an integer 0 ≤ M ≤ 200 and M lines in the form B1 B2 will follow, indicating that beverage B2 has more alcohol that beverage B1, so Dilbert should drink beverage B1 before he starts drinking beverage B2. Be sure that this relation is transitive, so if there is also a relation B2 B3 you should drink B1 before you can drink B3. There is a blank line after each test case. In the case there is no relation between two beverages Dilbert should start drinking the one that appears first in the input. The input is terminated by end of file (EOF).

Output

For each test case you must print the message: Case #C: Dilbert should drink beverages in this order: B1 B2 ... BN., where C is the number of the test case, starting from 1, and B1 B2 ... BN is a list of the beverages such that the alcohol content of beverage Bi+1 is not less than the alcohol content of beverage Bi-1. After each test case you must print a blank line.

Sample Input

3
vodka
wine
beer
2
wine vodka
beer wine

5
wine
beer
rum
apple-juice
cachaca
6
beer cachaca
apple-juice beer
apple-juice rum
beer rum
beer wine
wine cachaca

10
cachaca
rum
apple-juice
tequila
whiskey
wine
vodka
beer
martini
gin
11
beer whiskey
apple-juice gin
rum cachaca
vodka tequila
apple-juice martini
rum gin
wine whiskey
apple-juice beer
beer rum
wine vodka
beer tequila

Sample Output

Case #1: Dilbert should drink beverages in this order: beer wine vodka.

Case #2: Dilbert should drink beverages in this order: apple-juice beer wine rum cachaca.

Case #3: Dilbert should drink beverages in this order: apple-juice wine vodka beer rum cachaca tequila whiskey martini gin.


Problem setter: Sérgio Queiroz de Medeiros
Topological sort + priority queue
#include<stdio.h>
#include<cstring>
#include<string>
#include<map>
#include<queue>
#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,cnt[100],cases=1;
vector<int>egs[100];
map<string,int>mp;
vector<string>name;
void ans(){
vector<int>res;
int top=-1,cur,b;
priority_queue<pair<int,int> >q;
rep(i,N){
if(!cnt[i]){
if(DBG)printf("cnt[%d]=0\n",i);
q.push(make_pair(-1*i,i));
}
}
rep(i,N){
cur=q.top().second,q.pop();
if(DBG)printf("cur %d\n",cur+1);
res.push_back(cur);
rep(j,egs[cur].size()){
b=egs[cur][j];
cnt[b]--;
if(!cnt[b])q.push(make_pair(-1*b,b));
}
}
bool ll=0;
printf("Case #%d: Dilbert should drink beverages in this order: ",cases++);
rep(i,res.size()){if(ll)printf(" ");ll=1;printf("%s",name[res[i]].c_str());}
printf(".\n\n");
}
int main(){
char chs[100],chs2[100];
int m,a,b,num;
while(scanf("%d",&N)==1){
num=0,name.clear(),mp.clear(),memset(cnt,0,sizeof(cnt));
rep(i,100)egs[i].clear();
rep(i,N)scanf("%s",chs),mp[chs]=num++,name.push_back(chs);
scanf("%d",&m);
rep(i,m)scanf("%s%s",chs,chs2),a=mp[chs],b=mp[chs2],egs[a].push_back(b),cnt[b]++;
ans();
}
}

uva 872 - Ordering


Ordering
Background
   Order is an important concept in mathematics and in computer science. For example, Zorns Lemma states: a partially ordered set in which every chain has an upper bound contains a maximal element. Order is also important in reasoning about the fix-point semantics of programs.
    This problem involves neither Zorns Lemma nor fix-point semantics, but does involve order.
Problem
   Given a list of variable constraints of the form A < B, you are to write a program that prints all orderings of the variables that are consistent with the constraints. For example, given the contraints A < B and A < C there are two orderings of the variables AB and C that are consistent with these constraints: ABC and ACB.
Input
The input begins with a single positive integer on a line by itself indicating the number of the cases following, each of them as described below. This line is followed by a blank line, and there is also a blank line between two consecutive inputs.

   The input consists of two lines: a list of variables on one line, followed by a list of constraints of the form A < B on the next line. Variables and contraints are separated by single spaces.
   All variables are single character, upper-case letters. There will be at least two variables, and no more than 20 variables. There will be at least one constraint, and no more than 50 constraints. There will be no more than 300 orderings consistent with the contraints in a specification.
Output
For each test case, the output must follow the description below. The outputs of two consecutive cases will be separated by a blank line.

   All orderings consistent with the constraints should be printed. Orderings are printed in alphabetical order, one per line. Characters on a line are separated by a space. If no ordering is possible, the output is a single line with the word NO.

Sample Input

1

A B F G
A<B B<F

Sample Output

A B F G
A B G F
A G B F
G A B F



Gabriel David, CPUP'2000 Round 2
Concurso de Programa��o da Universidade do Porto


Topological sort
#include<stdio.h>
#include<sstream>
#include<cstring>
#include<string>
#include<vector>
#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
using namespace std;

int N,cnt[26];
bool trav[26];
vector<int>sym;
vector<int>egs[26];
vector<string>res;
void topo(string s){
    if(s.size()==N){if(DBG)printf("s %s\n",s.c_str());res.push_back(s);return;}
    int b,cnt2[26];
    rep(i,N){
        if(!trav[sym[i]]&&!cnt[sym[i]]){
            trav[sym[i]]=1;
            memcpy(cnt2,cnt,sizeof(cnt));
            rep(j,egs[sym[i]].size()){
                b=egs[sym[i]][j];
                cnt[b]--;
            }
            topo(s+char('A'+sym[i]));
            memcpy(cnt,cnt2,sizeof(cnt));
            trav[sym[i]]=0;
        }
    }
}
void ans(){
    res.clear();
    topo("");
    sort(res.begin(),res.end());
    bool ll;
    if(res.size())
        rep(i,res.size()){
            ll=0;
            rep(j,res[i].size()){if(ll)printf(" ");ll=1;printf("%c",res[i][j]);}
            printf("\n");
        }
    else printf("NO\n");
}
void getO(string s){
    if(DBG)printf("%c<%c\n",s[0],s[2]);
    egs[s[0]-'A'].push_back(s[2]-'A');
    cnt[s[2]-'A']++;
}
int main(){
    char chs[200];
    stringstream buf;
    int n;
    bool ll=0;
    string s;
    scanf("%d",&n);
    rep(i,n){
        sym.clear();rep(i,20)egs[i].clear();
        memset(cnt,0,sizeof(cnt));
        scanf(" ");
        fgets(chs,200,stdin);if(chs[strlen(chs)-1]=='\n')chs[strlen(chs)-1]='\0';
        buf.clear(),buf.str(chs);
        while(!buf.eof())buf>>s,sym.push_back(s[0]-'A');
        if(DBG){printf("sym: ");rep(i,sym.size())printf("%c ",sym[i]+'A');printf("\n");}
        fgets(chs,200,stdin);if(chs[strlen(chs)-1]=='\n')chs[strlen(chs)-1]='\0';
        buf.clear(),buf.str(chs);
        while(!buf.eof())buf>>s,getO(s);
        N=sym.size();
        sort(sym.begin(),sym.end());
        if(ll)printf("\n");ll=1;
        ans();
    }
}

uva 11902 - Dominator


D
Dominator
In graph theory, a node X dominates a node Y if every path from the predefined start node to Y must go through X. If Y is not reachable from the start node then node Y does not have any dominator. By definition, every node reachable from the start node dominates itself. In this problem, you will be given a directed graph and you have to find the dominators of every node where the 0th node is the start node.
As an example, for the graph shown right, 3 dominates 4 since all the paths from 0 to 4 must pass through 31 doesn't dominate 3 since there is a path 0-2-3 that doesn't include 1.

Input

The first line of input will contain T (≤ 100) denoting the number of cases.
Each case starts with an integer N (0 < N < 100) that represents the number of nodes in the graph. The next N lines contain N integers each. If the jth(0 based) integer of ith(0 based) line is 1, it means that there is an edge from node i to node j and similarly a 0 means there is no edge.

Output

For each case, output the case number first. Then output 2N+1 lines that summarizes the dominator relationship between every pair of nodes. If node A dominates node B, output 'Y' in cell (A, B), otherwise output 'N'Cell (A, B) means cell atAth row and Bth column. Surround the output with |+ and  to make it more legible. Look at the samples for exact format.

Sample Input

Output for Sample Input

2
5
0 1 1 0 0
0 0 0 1 0
0 0 0 1 0
0 0 0 0 1
0 0 0 0 0
1
1
Case 1:
+---------+
|Y|Y|Y|Y|Y|
+---------+
|N|Y|N|N|N|
+---------+
|N|N|Y|N|N|
+---------+
|N|N|N|Y|Y|
+---------+
|N|N|N|N|Y|
+---------+
Case 2:
+-+
|Y|
+-+


Problem Setter: Sohel Hafiz, Special Thanks: Kazi Rakibul Hossain, Jane Alam Jan
Graph Traversal, graph theory(reference)

#include<stdio.h>
#include<cstdlib>
#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 R,cases=1;
vector<int>egs[100],node;
bool trav[100],dom[100][100],rec[100];
void DT(int cur,int nop){
    int b;
    if(DBG)printf("cur %d ",cur);
    trav[cur]=1;
    rep(i,egs[cur].size()){
        b=egs[cur][i];
        if(b==nop)continue;
        if(!trav[b])DT(b,nop);
    }
}
void DFS(int cur){
    int b;
    trav[cur]=1;
    node.push_back(cur);
    rep(i,egs[cur].size()){
        b=egs[cur][i];
        if(!trav[b])DFS(b);
    }
}
void print(){
    printf("child(%d): ",node.size());
    rep(i,node.size())printf("%d ",node[i]);
}
void ans(){
    int b;
    node.clear();
    memset(trav,0,sizeof(trav));
    memset(dom,0,sizeof(dom));
    DFS(0);if(DBG)print();
    memcpy(rec,trav,sizeof(trav));
    rep(i,R)if(trav[i])dom[0][i]=1;
    REP(i,1,node.size()){
        b=node[i],memset(trav,0,sizeof(trav));
        DT(0,b);
        rep(j,R)if(rec[j]&&!trav[j])dom[b][j]=1;
    }       
    printf("Case %d:\n",cases++);
    printf("+");rep(i,R)if(i==0)printf("-");else printf("--");printf("+\n");
    rep(i,R){
        printf("|");
        rep(j,R){if(dom[i][j])printf("Y");else printf("N");printf("|");}
        printf("\n");
        printf("+");rep(i,R)if(i==0)printf("-");else printf("--");printf("+\n");
    }
}
int main(){
    int n,a;
    scanf("%d",&n);
    rep(i,n){
        scanf("%d",&R);
        rep(i,100)egs[i].clear();
        rep(i,R)rep(j,R){scanf("%d",&a);if(a)egs[i].push_back(j);}
        ans();
    }
}

2012年9月24日 星期一

uva 168 - Theseus and the Minotaur



 Theseus and the Minotaur 

Those of you with a classical education may remember the legend of Theseus and the Minotaur. This is an unlikely tale involving a bull headed monster, an underground maze full of twisty little passages all alike, love-lorn damsels and balls of silk. In line with the educational nature of this contest, we will now reveal the true story.

The maze was actually a series of caverns connected by reasonably straight passages, some of which could only be traversed in one direction. In order to trap the Minotaur, Theseus smuggled a large supply of candles into the Labyrinth, as he had discovered that the Minotaur was afraid of light. Theseus wandered around somewhat aimlessly until he heard the Minotaur approaching along a tunnel. At this point he lit a candle and set off in pursuit. The Minotaur retreated into the cavern it had just left and fled by another passage. Theseus followed, slowly gaining, until he reached the k'th cavern since lighting the candle. Here he had enough time to place the lighted candle in the middle of the cavern, light another one from it, and continue the chase. As the chase progressed, a candle was left in each k'th cavern passed through, thereby limiting the movement of the Minotaur. Whenever the Minotaur entered a cavern, it would check the exits in a particular order, fleeing down the first that did not lead directly to a lit cavern. (Remember that as Theseus was carrying a lit candle, the Minotaur never exited a cavern by the tunnel used to enter it.) Eventually the Minotaur became trapped, enabling Theseus to defeat it.

Consider the following Labyrinth as an example, where in this case the Minotaur checks the exits from a cavern in alphabetical order:

picture23

Assume that Theseus is in cavern C when he hears the Minotaur approaching from A, and that for this scenario, the value of k is 3. He lights a candle and gives chase, pursuing it through A, B, D (leaves a candle), G, E, F (another candle), H, E, G (another), H, E (trapped).

Write a program that will simulate Theseus's pursuit of the Minotaur. The description of a labyrinth will identify each cavern by an upper case character and will list the caverns reachable from that cavern in the order that the Minotaur will attempt them, followed by the identifiers for the caverns which the Minotaur and Theseus were in when contact was first made, followed by the value of k. If a cavern has no exit it may or may not be in the input.

Input

Input will consist of a series of lines. Each line will describe a scenario in the format shown below (which describes the above example). No line will contain more than 255 characters. The file will be terminated by a line consisting of a single #.

Output

Output will consist of one line for each Labyrinth. Each line will identify the lit caverns, in the order in which the candles were left, and the cavern in which the Minotaur was trapped, following the format shown in the example below.

Sample input


A:BCD;B:AD;D:BG;F:H;G:DEH;E:FGH;H:EG;C:AD. A C 3
#

Sample output


D F G /E

Graph Traversal
#include<stdio.h>
#include<cstdlib>
#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 A,B,L,K;
vector<int>egs[26],lc;
bool lit[26];
void DFS(int from,int cur,int len){
if(DBG)printf("DFS cur len %c %d\n",cur+'A',len);
bool final=1;
if(len==K)lit[cur]=1,lc.push_back(cur),len=0; //only lit when not trapped
int a;
rep(i,egs[cur].size()){
a=egs[cur][i];
if(!lit[a]&&a!=from){DFS(cur,a,len+1),final=0;break;}
}
if(final){ //only lit when not trapped
L=cur;
if(lc.size()&&lc.back()==cur)lc.pop_back();
}
}
void ans(){
memset(lit,0,sizeof(lit));
lc.clear();
int c;
bool ll=0;
DFS(B,A,1);
rep(i,lc.size()){if(ll)printf(" ");ll=1,printf("%c",'A'+lc[i]);}
if(lc.size())printf(" /%c\n",L+'A');
else printf("/%c\n",L+'A');
}
int getE(string s){
int cur=0,next=0,cc,end;
string a;
rep(i,26)egs[i].clear();
while(1){
next=s.find(";",cur);
if(next==string::npos)break;
a=s.substr(cur,next-cur);
if(DBG)printf("a: %s\n",a.c_str());
cc=a[0]-'A';
rep(i,a.size()-2)egs[cc].push_back(a[2+i]-'A');
cur=next+1;
}
cc=s[cur]-'A';
if(DBG)printf("s: %s\n",s.substr(cur,s.find(".",0)-cur).c_str());
end=s.find(".",0);
REP(i,cur+2,end)egs[cc].push_back(s[i]-'A');
if(DBG)rep(i,26){
if(egs[i].size()){printf("%c: ",char(i+'A'));rep(j,egs[i].size())printf("%c",egs[i][j]+'A');}
printf("\n");
}
return end;
}
int main(){
int a;
char chs[280];
while(fgets(chs,280,stdin)){
if(chs[0]=='#')break;
if(chs[strlen(chs)-1]=='\n')chs[strlen(chs)-1]='\0';
a=getE(chs);
A=chs[a+2]-'A',B=chs[a+4]-'A',K=atoi(&chs[a+6]);
if(DBG)printf("from to k %c %c %d\n",A+'A',B+'A',K);
ans();
}
}

2012年9月20日 星期四

uva 10422 - Knights in FEN


Problem D

Knights in FEN

Input: standard input
Output: standard output
Time Limit: 10 seconds

There are black and white knights on a 5 by 5 chessboard. There are twelve of each color, and there is one square that is empty. At any time, a knight can move into an empty square as long as it moves like a knight in normal chess (what else did you expect?).
Given an initial position of the board, the question is: what is the minimum number of moves in which we can reach the final position which is:
Input
First line of the input file contains an integer N (N<14 are="are" below:="below:" description="description" each="each" given="given" how="how" indicates="indicates" inputs="inputs" is="is" many="many" of="of" p="p" set="set" sets="sets" that="that" the="the" there.="there.">
Each set consists of five lines; each line represents one row of a chessboard. The positions occupied by white knights are marked by 0 and the positions occupied by black knights are marked by 1. The space corresponds to the empty square on board.
There is no blank line between the two sets of input.
The first set of the sample input below corresponds to this configuration:
Output
For each set your task is to find the minimum number of moves leading from the starting input configuration to the final one. If that number is bigger than 10, then output one line stating
Unsolvable in less than 11 move(s).

otherwise output one line stating
Solvable in n move(s).
where n <= 10.
The output for each set is produced in a single line as shown in the sample output.

Sample Input

2
01011
110 1
01110
01010
00100
10110
01 11
10111
01001
00000

Sample Output

Unsolvable in less than 11 move(s).
Solvable in 7 move(s).


(Problem Setter: Piotr Rudnicki, University of Alberta, Canada)


A man is as great as his dreams.”

 DFS+ bitmask + backtracking

#include<stdio.h>
#include<cstring>
#include<string>
#include<vector>
#include<set>
#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
using namespace std;

struct Node{
    Node(){}
    Node(int a,int b,int c):val(a),row(b),col(c){}
    int val,row,col;
    bool operator <(Node b)const{return val<b.val||row<b.row||col<b.col;}
};
int T,bnum=13;
set<Node>st;
int bottom[]= {5,10,11,12,15,16,17,18,20,21,22,23,24};
char chess[5][10],dir[8][2];
void init(){
    rep(i,5)T<<=1,T+=1;
    T<<=1;
    rep(i,4)T<<=1,T+=1;
    rep(i,3)T<<=1; rep(i,2)T<<=1,T+=1;
    rep(i,4)T<<=1;T<<=1,T+=1;
    rep(i,5)T<<=1;
    dir[0][0]=-2,dir[0][1]=-1,
    dir[1][0]=-2,dir[1][1]=1,
    dir[2][0]=-1,dir[2][1]=-2,
    dir[3][0]=-1,dir[3][1]=2,
    dir[4][0]=1,dir[4][1]=-2,
    dir[5][0]=1,dir[5][1]=2,
    dir[6][0]=2,dir[6][1]=-1,
    dir[7][0]=2,dir[7][1]=1;
}
void getHole(int &a,int &b){
    rep(i,5)rep(j,5)if(chess[i][j]==' ')a=i,b=j;
}
bool getH(int a,int b){
    return (a>>24-b)%2;
}
int setH(int a,int pos,int b){
    if(b)a|=1<<(24-pos);
    else a-=(a & (1<<(24-pos)) );
    return a;
}
int count(int c){
    int a=0;
    rep(i,bnum){if(getH(c,bottom[i]))a++;}
    if(DBG)printf("cnt: %d\n",a);
    return a;
}
int getC(){
    int c=0;
    rep(i,5)rep(j,5){
        if(chess[i][j]=='1')c<<=1,c+=1;
        else c<<=1;
    }
    return c;
}
int move(int v,int cr,int cc,int nr,int nc){
    int from=cr*5+cc,to=nr*5+nc;
    int h=getH(v,from);
    v=setH(v,from,0);
    v=setH(v,to,h);         //move
    return v;
}
bool valid(int a,int b){return a>=0&&a<5&&b>=0&&b<5;}
void print(int a){
    rep(i,5){
        rep(j,5)printf("%d",getH(a,i*5+j));
        printf("\n");
    }
}
void ans(){
    int cur,dis,next,cr,cc,nr,nc;
    bool h;
    Node nd;
    int res=11;
    st.clear();
    getHole(cr,cc);
    queue<pair<Node,int> >q;
    nd=Node(getC(),cr,cc);
    st.insert(nd);
    q.push(make_pair(nd,0));
    while(q.size()){
        cur=q.front().first.val,dis=q.front().second,
        cr=q.front().first.row,cc=q.front().first.col;
        if(DBG){printf("cur\n");print(cur);printf("cur cr cc dis %d %d %d %d\n",cur,cr,cc,dis);}
        q.pop();
        if(dis>10)break;
        if(count(cur)>10-dis)continue;
        if(cur==T&&cr==2&&cc==2){res=dis;break;}
        rep(i,8){
            nr=cr+dir[i][0],nc=cc+dir[i][1];
            if(valid(nr,nc)){
                if(DBG)printf("new hole %d %d\n",nr,nc);
                next=move(cur,nr,nc,cr,cc);
                nd=Node(next,nr,nc);
                if(!st.count(nd))
                    st.insert(nd),q.push(make_pair(Node(next,nr,nc),dis+1));
            }
        }
    }
    if(res>10)printf("Unsolvable in less than 11 move(s).\n");
    else printf("Solvable in %d move(s).\n",res);
}
int main(){
    int n;
    scanf("%d ",&n);
    init();
    rep(i,n){
        rep(i,5)fgets(chess[i],10,stdin);
        ans();
    }
}

uva 10400 - Game Show Math


Problem H
Game Show Math
Input: standard input
Output: standard output
Time Limit: 15 seconds
A game show in Britain has a segment where it gives its contestants a sequence of positive numbers and a target number. The contestant must make a mathematical expression using all of the numbers in the sequence and only the operators: +-,*, and, /. Each number in the sequence must be used exactly once, but each operator may be used zero to many times. The expression should be read from left to right, without regard for order of operations, to calculate the target number. It is possible that no expression can generate the target number. It is possible that many expressions can generate the target number.
There are three restrictions on the composition of the mathematical expression:
o  the numbers in the expression must appear in the same order as they appear in the input file
o  since the target will always be an integer value (a positive number), you are only allowed to use / in the expression when the result will give a remainder of zero.
o  you are only allowed to use an operator in the expression, if its result after applying that operator is an integer from (-32000 .. +32000).
Input
The input file describes multiple test cases. The first line contains the number of test cases n.
Each subsequent line contains the number of positive numbers in the sequence p, followed by p positive numbers, followed by the target number. Note that 0 < p £ 100. There may be duplicate numbers in the sequence. But all the numbers are less than 32000.
Output
The output file should contain an expression, including all k numbers and (k-1) operators plus the equals sign and the target. Do not include spaces in your expression. Remember that order of operations does not apply here. If there is no expression possible output "NO EXPRESSION(without the quotes). If more than one expression is possible, any one of them will do.

Sample Input
3
3 5 7 4 3
2 1 1 2000
5 12 2 5 1 2 4
Sample Output
5+7/4=3
NO EXPRESSION
12-2/5*1*2=4

(Problem-setter: Sandy Graham, CS Dept, University of Waterloo)

DFS + backtracking


#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,T,data[100];
bool trav[100][64001];
string res;
bool valid(int a){return a>=-32000&&a<=32000;}
bool DFS(int ind,int num,string s){
if(DBG)printf("dfs ind num %d %d\n",ind ,num);
if(ind==N){
if(num==T){res=s;return 1;}
return 0;
}
if(trav[ind][num+32000])return 0;
trav[ind][num+32000]=1;
if(valid(num+data[ind])&&DFS(ind+1,num+data[ind],s+'+'))return 1;
if(valid(num-data[ind])&&DFS(ind+1,num-data[ind],s+'-'))return 1;
if(valid(num*data[ind])&&DFS(ind+1,num*data[ind],s+'*'))return 1;
if(data[ind]!=0&&num%data[ind]==0&&valid(num*data[ind])&&DFS(ind+1,num/data[ind],s+'/'))return 1;
return 0;
}
void print(){
printf("%d",data[0]);
rep(i,res.size()){
printf("%c%d",res[i],data[i+1]);
}
printf("=%d\n",T);
}
void ans(){
int tot=0;
memset(trav,0,sizeof(trav));
if(DFS(1,data[0],""))print();
else printf("NO EXPRESSION\n");
}
int main(){
int n;
scanf("%d",&n);
rep(i,n){
scanf("%d",&N);
rep(i,N)scanf("%d",&data[i]);scanf("%d",&T);
if(DBG)printf("T %d\n",T);
ans();
}
}