【2013-2014ACM-ICPCBrazilSubregionalProgrammingContest】

【Problem A-Zero or One】

【Description】Everyone probably knows the game Zero or One (in some regions in Brazil also known as Two or One), used to determine a winner among three or more players. For those unfamiliar, the game works as follows. Each player chooses a value between zero or one; prompted by a command (usually one of the contestants announces \Zero or... One!"), all participants show the value chosen using a hand: if the value chosen is one, the contestant shows a hand with an extended index finger; if the value chosen is zero, the contestant shows a hand with all fingers closed. The winner is the one who has chosen a value different from all others. If there is no player with a value different from all others (e.g. all players choose zero, or some players choose zero and some players choose one), there is no winner. Alice, Bob and Clara are great friends and play Zerinho all the time: to determine who will buy popcorn during the movie session, who will enter the swimming pool first, etc.. They play so much that they decided make a plugin to play Zerinho on Facebook. But since the don’t know how to program computers, they divided the tasks among friends who do know, including you. Given the three values chosen by Alice, Bob and Clara, each value zero or one, write a program that determines if there is a winner, and in that case determines who is the winner.

【Input】

The input contains a single line, with three integers A, B and C, indicating respectively the values chosen by Alice, Beto and Clara.

【Output】

Your program must output a single line, containing a single character. If Alice is the winner the character must be ‘A’, if Beto is the winner the character must be ‘B’, if Clara is the winner the character must be ‘C’, and if there is no winner the character must be ‘*’ (asterisc).

【題目大意】

三個人每個人為0或1摄杂,單獨的那一個勝利,輸出ABC循榆。如果沒有單獨的輸出’*’析恢。

【分析】

沒得分析

int main(){

int he=0,a,b,c;

scanf("%d%d%d",&a,&b,&c);

he=a+b+c;

if(he==1) {

   if(a==1)printf("A");

   if(b==1)printf("B");

   if(c==1)printf("C");

}

else if(he==2)   {

   if(a==0)printf("A");

   if(b==0)printf("B");

   if(c==0)printf("C");

}

else printf("*");

}

=================================================================

【Problem C-Boss】

【Description】Everyone knows Iks, the last trend in social network, which made so much success that competitors like Facebook and Google+ are struggling to keep their own social networks in business. As several ".com" companies, Iks started in a small garage, but today employs hundreds of thousands. Iks has also a non-standard management system. For example, there are no committees or boards,

which means less time spent on internal meeting. However, as usual in other companies, there is a chain (or rather several chains) of command, as a person may manage other employees, and may be managed by other employees. A person P1 may manage another person P2 directly (when P1 is the immediate superior of P1) or indirectly (when P1 manages directly a person P3 who manages P2 directly or indirectly). A person does not manage himself/herself, either directly or indirectly. One folklore that developed in Wall Street is that Iks is so successful because in its chain of command a manager is always younger than the managed employee. As we can see in figure above, that is not true. But this folklore prompted Iks to develop a tool to study its own management system, and to understand whether age plays a role in its success. You have been hired to work on that tool. Given the description of the chain of command at Iks and the ages of its employees, write a program that answers a series of instructions. Instructions are of two types: management change and query. An instruction of management change swaps the positions of two employees A and B.

【Input】

Each test case is described using several lines. The first line of a test case contains three integers N, M and I, representing respectively the number of employees, the number of direct manage relations and the number of instructions. Employees are identified by numbers from 1 to N. The second line contains N integers Ki, where Ki indicates the age of the employee number i. Each of the following M lines contains two integers X and Y , indicating that X manages Y directly. Then it follows I lines, each describing an instruction. An instruction of type management change is described by a line containing the identifier T followed by two integers A and B, indicating the two employers that must swap places in the chain of command. An instruction of type query is described by a line containing the identifier P followed by one integer E, representing the number of an employer. The last instruction is of type query.

【Output】

For each instruction of type query your program must print a single line containing a single integer, the age of the employee who is the youngest person that manages the employer named in the query (directly or indirectly), if that person exists. If the employee does not have a manager, print an ‘*’ (asterisc).

【題目大意】

職場工作中有上下級的命令關(guān)系,稱之為命令鏈⊙硪現(xiàn)在給N名員工映挂,M條命令關(guān)系。員工的年齡在其后給出盗尸,緊接著M行x y表示x員工是y員工直接上級袖肥,在緊接著I行,每次表示修改或查詢振劳。修改則將兩名員工的管理關(guān)系對換,查詢則查詢某個員工的所有上級中最年輕的幾歲油狂。如果沒有輸出*历恐。

【分析】

Waiting for complement;

using namespace std;

typedef long long LL;

define maxn 510

define maxm 60100

struct node{

int y,next;

}a[maxm];int first[maxn],len;

int id[maxn],w[maxn],d[maxn];

void ins(int x,int y){

len++;a[len].y=y;

a[len].next=first[x];first[x]=len;

}

int ans;bool bo[maxn];

int mymin(int x,int y){return (x

void dfs(int x,int rt){

if (bo[x]) return;

bo[x]=true;

if (x!=rt) {

   if (ans==-1) ans=d[id[x]];

   else ans=mymin(ans,d[id[x]]);

}

for (int k=first[x];k!=-1;k=a[k].next) {

   int y=a[k].y;

   dfs(y,rt);

}

}

int main(){

int n,m,q,i,x,y;char c;

scanf("%d%d%d",&n,&m,&q);

len=0;memset(first,-1,sizeof(first));

for (i=1;i<=n;i++){

   scanf("%d",&d[i]);

   id[i]=i;w[i]=i;

   //id[i]表示第i個位置是哪號人

   //w[i]表示第i號人在第幾個位置

}

//建圖是建的位置

for (i=1;i<=m;i++){

   scanf("%d%d",&x,&y);

   ins(y,x);

}

while (q--){

   scanf("%c",&c);

   while (c!='P' && c!='T') scanf("%c",&c);

   if (c=='P') {

       scanf("%d",&x);

       memset(bo,false,sizeof(bo));

       ans=-1;dfs(w[x],w[x]);

       if (ans==-1) printf("*\n");

       else printf("%d\n",ans);

   }else if (c=='T') {

       scanf("%d%d",&x,&y);

       int tt=w[x];w[x]=w[y];w[y]=tt;

       id[w[x]]=x;id[w[y]]=y;

   }

}

return 0;

}

=================================================================

【Problem D-Folding Machine】

【Description】 One of the main tools of a Turing machine, which allows its computing power to be bigger than other simpler models, is an infinite tape, divided in cells, where information is stored. A Folding machine is a machine inspired by a Turing machine. In a Folding machine, the tape is finite, the data are integers and instead of having the functionality of the original Turing machine,

this machine uses folding tape operations. To perform a folding operation, the machine chooses a position between adjacent cells and folds the tape, adding the values of overlapping cells. Notice that the machine can also fold the tape before the tape center, as shown in the next figure. The machine can also choose to fold at the tape start or at the tape end, actually inverting the tape. Science of Bends Company is developing commercial versions of their Folding machine and its production have recently raised. The last lot produced, unfortunately, have some issues and some machines aren’t working properly. Some additional testing is therefore needed, to avoid selling defective machines, which would denigrate the company’s image. To test these machines, a set of tests and tapes are given. For each tape, the machine returns some computation result. Therefore, the engineers responsible for testing take note of the results and can verify if they are correct. But these engineers forgot to take note of which computation was made in each test case. To avoid re-testing all machines again, the engineers agreed that any combination of foldings is sound and accepted if, from a given input, it generates the expected output. You were hired to develop a program which, given the input and output tapes, determines whether there is a folding sequence that, starting from the input tape, generates the output tape.

【Input】

The input contains four lines. The first two lines refer to the input tape for the Folding machine and the last two lines refer to the output tape. The first line contains a single number, N, describing the input tape size. The second line contains N integers v1…vN describing the content of the input tape. The third line contains a single integer M, the output tape size; and the fourth line contains M integers w1…wM, the content of the output tape.

【Output】

You program must produce a single line, containing a single character, which must be "S" if there is a folding sequence able to generate the output tape starting from the input tape, and "N" otherwise.

【題目大意】

一條紙帶上許多格子,從某處對折后貼在一起的格子內(nèi)的數(shù)字可以相加专筷。在折疊過后紙帶可以不展開的前提下繼續(xù)折疊∪踉簦現(xiàn)在給初始紙帶狀態(tài)和最終狀態(tài),問能否通過折疊得到最終狀態(tài)磷蛹,輸出是S否N吮旅。

【分析】

暴力搜索從哪里開始疊

typedef long long LL;

LL b[20];int m; bool bk;

void dfs(LL a[],int t) {

if (bk) return; if (t

if (t==m)  {

   bool bo=true;

   for (int i=1;i<=m;i++) if (b[i]!=a[i]) {bo=false;break;}

    if (bo) bk=true;

   bo=true;

   for (int i=1;i<=m;i++) if (b[i]!=a[t-i+1]) {bo=false;break;}

   if (bo) bk=true;

   return;

}

LL c[20];

for (int i=1;i

   if (i*2

       for (int j=1;j<=t-i;j++) {

          if (j<=t-i*2) c[j]=a[t-j+1];

          else c[j]=a[t-j+1]+a[2*i-t+j];

       }

       dfs(c,t-i);

   }else {

       for (int j=1;j<=i;j++) {

          if (j<=2*i-t) c[j]=a[j];

          else c[j]=a[j]+a[2*i-j+1];

       }

       dfs(c,i);

   }

}

}

int main(){

int i,n;LL a[20]; bk=false;

scanf("%d",&n); for (i=1;i<=n;i++)  scanf("%I64d",&a[i]);

scanf("%d",&m); for (i=1;i<=m;i++)  scanf("%I64d",&b[i]);

dfs(a,n); if (bk) printf("S\n"); else printf("N\n");

return 0;

}

=================================================================

【Problem E-Dangerous Dive】

【Description】 The recent earthquake in Nlogonia did not affect too much the buildings in the capital, which was at the epicenter of the quake. But the scientists found that it affected the dike wall, which now has a significant structural failure in its underground part that, if not repaired quickly, can cause the

collapse of the dike, with the consequent flooding the whole capital.

The repair must be done by divers, at a large depth, under extremely difficult and dangerous

conditions. But since the survival of the city is at stake, its residents came out in large numbers to

volunteer for this dangerous mission.

As is traditional in dangerous missions, each diver received at the start of his/her mission a small

card with an identification number. At the end of their mission, the volunteers returned the nameplate,

placing it in a repository.

The dike is safe again, but unfortunately it seems that some volunteers did not return from their

missions. You were hired for the grueling task of, given the plates placed in the repository, determine

which volunteers lost their lives to save the city.

Input

The input is composed of two lines. The first line contains two integers N and R, indicating respectively

the number of volunteers that went to the mission and the number of volunteers that returned from

the mission. Volunteers are identified by numbers from 1 to N. The second line contains R integers,

indicating the volunteers which returned from the mission (at least one volunteer returned).

Output

Your program must produce a single line containing the identifiers of the volunteers who did not

return from their missions, in ascending order of their identifications. Leave a blank space after each

identifier (notice that, therefore, there must be a blank space after the last identifier in the line). If

every volunteer returned, the line must contain a single character ‘*’ (asterisc).

【題目大意】

地震志愿者blahblah,輸出沒來的志愿者多少個味咳。

【分析】

模擬

Waiting for complement;

bool bk[maxn];

int main(){

int n,m,i,x,cnt;

memset(bk,false,sizeof(bk));

scanf("%d%d",&n,&m);cnt=n;

for (i=1;i<=m;i++){

   scanf("%d",&x);

   bk[x]=true;cnt--;

}

if (cnt==0) printf("*\n");

else{

   for (i=1;i<=n;i++)

     if (bk[i]==false){

        cnt--;

        if (cnt) printf("%d ",i);

        else {printf("%d \n",i);break;} 

     }

}

return 0;

}

=================================================================

【Problem F-Triangles】

【Description】You will be given N points on a circle. You must write a program to determine how many distinct equilateral triangles can be constructed using the given points as vertices.

【Input】

The first line of the input contains an integer N, the number of points given. The second line contains N integers Xi, representing the lengths of the circular arcs between two consecutive points in the circle: for 1 ≤ i ≤ (N ? 1), Xi represents the length of the arc between between points i and i + 1; XN represents the length of the arc between points N and 1.

【Output】

Your program must output a single line, containing a single integer, the number of distinct equilateral triangles that can be constructed using the given points as vertices.

【題目大意】

圓上n個點庇勃,選取三個作為三角形,問不同的選取方案之間是全等的三角形方案數(shù)有多少個槽驶。

【分析】

前綴和

int n,ans,bian;

int x[112345];

bool vis[112345]={0};

void judge(int m){

int sum=0,r=m;

while(r<=n)   {

   if(sum==bian) {ans++; vis[m]=1; }

   if(sum>bian) break;

   sum+=x[r++];

}

}

int main(){

int left=1,right=1,sum=0;

scanf("%d",&n);

for(int i=1;i<=n;i++){scanf("%d",&x[i]);bian+=x[i];   }

if(bian%3){printf("0");return 0;}

bian/=3;

while(right<=n)  {

   if(vis[left]==1)break;

   if(sum==bian)judge(right);

   if(sum>bian) {sum-=x[left];left++;continue;}

   sum+=x[right++];

}

printf("%d",ans);

}

=================================================================

【Problem G-Lines of Containers】

【Description】A shipment of Nlogs, the main export product from Nlogonia, is in the harbour, in containers, ready to be shipped. All containers have the same dimensions and all of them are cubes. Containers are organized in the cargo terminal in L lines and C columns, for a total of LC containers. Each container is marked with a distinct identification number, from 1 to LC. Each one of the L container lines will be loaded in a different ship. To make it simpler when unloading at each destination country, containers from a line must be organized such that the identifiers are in sequential order. More precisely, the first line must have the containers identified from 1 to C in increasing order, line 2 must have containers numbered from C + 1 to 2C (in increasing order), and so on until the last line. which will have containers numbered (L?1)C + 1 to LC (again, in increasing order). A crane is able to move either a full line or a full column of containers. It cannot move other groupments or individual containers. In night before the loading, a group of workers operated the cranes to swap shipment lines and columns as a way of protest because of low salaries. The loading must be done today, but before starting the containers must be reorganized as described previously. You must write a program which, given the information about the position of every container after the protest, determines whether you can reposition the containers in such way that every one of them is in its expected positions, using only cranes. If repositioning is possible, you must also calculate the smallest number of column and line swaps needed to do it.

【Input】 The first line of input contains two integers L and C which describe, respectively, the number of lines and columns of the shipment. The next L lines show the configuration of the containers after the workers protest. Each of these L lines will have C integers Xl;c indicating the position of a container. Every integer between 1 and LC appears exactly once in the input.

【Output】 Your program must produce a single line, containing a single integer, the minimum number of column and line swaps needed to place the containers in their original positions. If there is no way to place the containers in their original positions using only cranes, the line must contain only the character ‘*’.

【題目大意】

一個按先行后列順序填1~LC的LC矩陣责嚷,可以行交換,列交換掂铐。給出變化后的最終狀態(tài)罕拂,問最少幾步達到揍异,不能輸出*。

【分析】

分析爆班,未交換時衷掷,第i行的元素為(i-1)C+1 到 iC喧兄,第j列的元素%c都是定值浩姥,行交換時,同列的元素順序僅在列之內(nèi)變化答朋,不會破壞%c定值的特性碗旅。列交換時渡处,同行元素順序僅在同行內(nèi)變化,不會破壞區(qū)間所屬的性質(zhì)祟辟。檢查矩陣是否滿足上述兩個條件医瘫,最后答案轉(zhuǎn)化成行交換多少次,列交換多少次旧困。模擬即可醇份。

int main(){

int L,C;

int mat[311][311];

scanf("%d %d",&L,&C);

for(int i=1;i<=L;i++){

   for(int j=1;j<=C;j++){

       scanf("%d",&mat[i][j]);

       if( (1+(mat[i][1]-1)/C) !=

          (1+(mat[i][j]-1)/C) ){

          cout<<"*";return 0;

       }

   }

}

for(int j=1;j<=C;j++)

   for(int i=1;i<=L;i++)

       if(mat[i][j]%C!=mat[1][j]%C){

          cout<<"*";return 0;

       }

int he[400];

for(int i=1;i<=C;i++) he[i]=1+((mat[1][i]-1)%C);

int ans=0;

bool flag=true;

while(1){

   int i,j;

   for(i=1;i<=C;i++) if(he[i]!=i) break;

   if(i>C) break;

   for(j=1;j<=C;j++) if(he[j]==i) break;

   swap(he[j],he[i]);

   ans++;

}

for(int i=1;i<=L;i++) he[i]=1+(mat[i][1]-1)/C;

while(1){

   int i,j;

   for(i=1;i<=L;i++) if(he[i]!=i) break;

   if(i>L) break;

   for(j=1;j<=L;j++) if(he[j]==i) break;

   swap(he[j],he[i]);

   ans++;

}

cout<<ans;

return 0;

}

=================================================================

【Problem H-Buses】

【Description】Programming competitions usually require infrastructure and organization on the part of those responsible. A problem that frequently must be solved is regarding transportation. While participating in a recent competition, Ricardinho watched the buses and micro-buses used in the transportation of competitors, all lined up one behind the other as competitors disembarked. The vehicles were all from the same company, although had different paintings. Ricardinho began to wonder how many ways that line could be formed using buses and minibuse from that company. Each bus is 10 meters long, each minibus is 5 meters long. Given the total length of a line of buses and minibuses, and the number of different colors each buse or minibus may be painted, Ricardinho wants to know in how many ways such a line can be formed.

【Input】 The input contains a single line, containing three integers N; K and L, representing respectively the total length, in meters, of the line Ricky is considering, K indicates the number of different colors for micro-buses, and L represents the number of different colors for buses. Note that, as integers N, K and L may be very large, the use of 64 bits integers is recommended.

【Output】 As the number of different ways of forming the line can be very large, Ricardinho is interested in the last 6 digits of that quantity. Thus, your program should produce a single line containing exactly 6 digits, corresponding to the last digits of the solution.

【題目大意】

長為5的倍數(shù)的路面停滿了巴士。2種巴士吼具,小巴5m長僚纷,大巴10米長。恰好停滿路面拗盒,不存在超出的情況怖竭。小巴有k種顏色,大巴有l(wèi)種顏色陡蝇,(k痊臭,l極大,longlong)現(xiàn)在問有多少種不同的停車方案登夫。同種車型的同種顏色如果交換位置認為是同一種方案广匙。答案輸出最后6位,不足補零恼策。

【分析】

dp鸦致。不妨把所有長度先除5,有長為n的路面上停1m的車或2m的車涣楷。設(shè)f[n]表示前n米停車方案數(shù)分唾,明顯有f[n]= f[n-1]k + f[n-2]l,即(n-1)+1m小車(k種) 和(n-2)+2m小車(L種)狮斗,由于n極大鳍寂,所以要矩陣快速冪來加速。設(shè)矩陣【Fn】=【fn情龄,fn-1】迄汛,則【Fn+1】=【fn+1捍壤,fn】,【Fn+1】=【Fn】【T】鞍爱,【T】是一個22 的矩陣鹃觉,為【(k),(1)睹逃;(L)盗扇,(0)】。

const int mod=1e6;

ll n,K,L;

struct node{

ll t[2][2];

}a,b;

node pp(node x,node y){

node r;

for(int i=0;i<2;i++)

    for(int j=0;j<2;j++){

        r.t[i][j]=0;

        for(int k=0;k<2;k++)

            r.t[i][j]=(r.t[i][j]+x.t[i][k]*y.t[k][j])%mod;

    }

return r;

}

void quickpow(ll m){

while(m)    {

    if(m&1)a=pp(a,b);

    b=pp(b,b);

    m=m>>1;

}

}

int main(){

scanf("%I64d%I64d%I64d",&n,&K,&L);

K=K%mod;L=L%mod;

b.t[0][0]=K;b.t[0][1]=1;

b.t[1][0]=L;b.t[1][1]=0;

n=n/5;

if(n==1)printf("I64d\n",K);

else if(n==2)printf("I64d\n",(K*K+L)%mod);

else {

    a.t[0][0]=(K*K+L)%mod;

    a.t[0][1]=K;

    quickpow(n-2);

    printf("I64d\n",a.t[0][0]%mod);

}

return 0;

}

=================================================================

【Problem I-Patches】

【Description】Carlos is very concerned with the environment. Whenever possible, he tries to use less polluting

means of transport. He recently got a job close to home and is now using his bike to go to work.

Unfortunately, in the route between his home and his job there is a nail factory, and often some

nails fall from their trucks, and end up puncturing Carlos’ bike tires. Therefore he ends up having to

make several patches on the tires of his bike.

To make the repairs, Carlos uses two different types of patches. Both types are as wide as a bike

tire, but differ in length. As the cost of the patch is proportional to its length, Carlos is trying to find

a way to save money, using the least possible length of patches to make the repairs, without cutting

the patches.

The first step in repairing a tire is making a chalk mark on a position of the tire and then writing

down the distances, measured clockwise, of each of the holes in relation to the chalk mark. Each hole

must be completely covered by a patch. Carl~ao would like your help to determine, given the positions

of the holes, the most economic way to make the repair.

【Input】

The input contains two lines. The first line contains four integers N; C; T1 e T2. Integer N indicates

the number of holes in the tire, and C indicates the cirunference length of the tire, in centimeters.

The lengths of the patches in centimeters are given by integers T1 and T2. The second line contains

N integers Fi, representing the distance, in clockwise direction, from the chalk mark to hole i, in

centimeters.

【Output】

Your program must print a single line, containing a single integer, the smallest total length of patches

needed to make all the repairs.

【題目大意】

輪胎上有一些洞需要修補沉填,現(xiàn)在按順時針順序給出洞在圓周上的弧長位置疗隶,給長度為T1,T2的兩種膠貼,問把所有洞填補最少要多長的膠貼翼闹。

【分析】

常見的dp問題斑鼻。f[i][j]表示填補前i個洞最后一個用膠貼j的最短長度。(j=0或1表示t1,t2)猎荠。明顯的坚弱,對于每一個i,找到膠貼j所能覆蓋到的最遠的洞关摇,進行更新即可荒叶。
int main(){

int n,c,t1,t2;

scanf("%d %d %d %d",&n,&c,&t1,&t2);

if(t1>t2) swap(t1,t2);

int hol[1010];

for(int i=1;i<=n;i++)scanf("%d",&hol[i]);

int f[1010][2];

for(int i=1;i<=n;i++){int k;

   for(k=1;k<=i;k++) if(hol[k]+t1>=hol[i]) break;

   f[i][0]=min(f[k-1][0]+t1,f[k-1][1]+t1);

   for(k=1;k<=i;k++) if(hol[k]+t2>=hol[i]) break;

   f[i][1]=min(f[k-1][0]+t2,f[k-1][1]+t2);

}

cout<<min(f[n][0],f[n][1]);

return 0;

}

=================================================================

【Problem J-Trucks】

【Description】The Subtle Balloons Company (SBC) is the main balloon provider for programming contests; it has

huge factories and warehouses, as well as an extensive truck fleet to ensure the contestants’ happiness.

There are lots of competition sites in Nlogonia, and all of them hired SBC for supplying balloons

for their contests. Nlogonia is an archipelago connected by several bridges. Every island of Nlogonia

may have several regional sites and may also house several SBC warehouses.

When planning the routes for balloon deliveries, SBC faced a problem: for safety issues, every

bridge in Nlogonia has some maximum weight limit for vehicles which cross it. And because of the

great net weight of the transported merchandise, SBC operations’ chief asked you to write a program

to determine the maximum weight allowed to be transported between warehouses and competition

sites.

【Input】

The first line contains three integers N, M and S which indicate, respectively, the number of islands,

the number of bridges that connect the islands and the number of sites. The islands are numbered

from 1 to N.

Each of the next M lines describes a bridge. The description of a bridge consists in a line with

three integers A, B and W , indicating respectively the two islands connected by the bridge and the

maximum weight allowed in that bridge, in tons.

All bridges are two-way roads; every pair of islands is connected by at most one bridge; and it is

possible to reach every other island in the archipelago using only bridges (naturally it may be needed

to pass through other islands to do so).

Each of the next S lines describe a competition site and contains two integers L and H indicating,

respectively, the number of the island where this site is and the number of the island where the

wharehouse which will be used to deliver the balloons to the site is.

【Output】

For each site in the input, in the order they were given, your program must produce a single line,

containing a single integer, the biggest weight which can be transported by truck from the warehouse

to the site.

【題目大意】

有n座島嶼(1~N),m個雙向橋梁输虱,保證任意兩個島嶼互達些楣。每架橋梁有限重,現(xiàn)在詢問某兩個島嶼之間一輛運輸貨物的卡車最多可載重多少貨物宪睹。換句話說戈毒,在N個點m條邊的無向連通圖,詢問某兩點之間的所有可達路徑上權(quán)值最小的邊的最大值横堡。

【分析】

每次看最小限重的一座橋梁(邊),如果去掉這條邊不影響整個圖的連通性冠桃,那么不管是哪兩個島嶼命贴,都不會從這條橋梁上經(jīng)過。(易證)食听。這樣直到最后的圖變成樹胸蛛,這樣任意兩個島嶼之間的路徑是唯一的,問題也變得簡單了樱报。然而葬项,刪除邊總是不容易操作,添加邊容易迹蛤,故做最大生成樹民珍。按邊權(quán)從大到小排序襟士,構(gòu)建生成樹。問題轉(zhuǎn)化為樹上兩個節(jié)點之間的路徑上權(quán)值最小是哪條邊嚷量。很明顯可以用最近公共祖先來處理陋桂,倍增法完成祖先信息,記gw[x][i]表示從x到其2^i的祖先的路徑上權(quán)值最小的邊蝶溶,這樣答案就可以很方便的得出了嗜历。

Waiting for complement;

define maxn 40001

define maxl 25

using namespace std;

typedef struct

{

int u,v,w;

}edge;//這個結(jié)構(gòu)體用來存儲邊

edge E[110000];

vectoredges;

vectorG[maxn];//保存邊的數(shù)組

int grand[maxn][maxl],gw[maxn][maxl];//x向上跳2i次方的節(jié)點,x到他上面祖先2i次方的距離

int depth[maxn];//深度

int n,m,N;

void addedge(int x,int y,int w){//把邊保存起來的函數(shù)

edge a={x,y,w},b={y,x,w};

edges.push_back(a);

edges.push_back(b);

G[x].push_back(edges.size()-2);

G[y].push_back(edges.size()-1);

}

void dfs(int x){//dfs建圖

for(int i=1;i<=N;i++){//第一個幾點就全部都是0咯抖所,第二個節(jié)點就有變化了梨州,不理解的話建議復(fù)制代碼輸出下這些數(shù)組

   grand[x][i]=grand[grand[x][i-1]][i-1];

   gw[x][i]=min(gw[x][i-1],gw[grand[x][i-1]][i-1]);

   // if(grand[x][i]==0) break;

}

for(int i=0;i

   edge  e = edges[G[x][i]];

   if(e.v!=grand[x][0]){//這里我們保存的是雙向邊所以與他相連的邊不是他父親就是他兒子父親的話就不能執(zhí)行,不然就死循環(huán)了田轧。

       depth[e.v]=depth[x]+1;//他兒子的深度等于他爸爸的加1

          grand[e.v][0]=x;//與x相連那個節(jié)點的父親等于x

          gw[e.v][0]=e.w;//與x相連那個節(jié)點的距離等于這條邊的距離

          dfs(e.v);//深搜往下面建

   }

}

}

void Init(){

//n為節(jié)點個數(shù)

N = floor(log(n + 0.0) / log(2.0));//最多能跳的2^i祖先

depth[1]=0;//根結(jié)點的祖先不存在暴匠,用-1表示

memset(grand,0,sizeof(grand));

memset(gw,0x7f,sizeof(gw));

dfs(1);//以1為根節(jié)點建樹

// for(int i=1;i<=n;i++) cout<<depth[i]<<'+';cout<<endl;

}

int lca(int a,int b){

if(depth[a] > depth[b]) swap(a, b);//保證a在b上面,便于計算

int ans = 2147483647;

for(int i = N; i >= 0; i--) //類似于二進制拆分涯鲁,從大到小嘗試

    if(depth[a] < depth[b] && depth[grand[b][i]] >= depth[a])//a在b下面且b向上跳后不會到a上面

        ans =min(ans,gw[b][i]), b=grand[b][i];//先把深度較大的b往上跳



for(int j=N;j>=0;j--){//在同一高度了,他們一起向上跳,跳他們不相同節(jié)點巷查,當全都跳完之后grand[a][0]就是lca,上面有解釋哈。

    if(grand[a][j]!=grand[b][j]) {

       ans=min(ans,gw[a][j]); ans=min(ans,gw[b][j]);

        a=grand[a][j]; b=grand[b][j];

    }

}

// cout<<"="<<ans<<endl;

if(a!=b) { ans=min(ans,gw[a][0]); ans=min(ans,gw[b][0]); }



return ans;

}

int T[21000];

int cmp(const void *a,const void *b){

edge x=*(edge *)a;

edge y=*(edge *)b;

return x.w>y.w?-1:1;

}

int find(int x){

if(T[x]==x) return x;

else return T[x]=find(T[x]);

}

int main()

{

int q;

scanf("%d %d %d",&n,&m,&q);  

for(int i=1;i<=m;i++) {

   int x,y,w;

   scanf("%d %d %d",&x,&y,&w);

   E[i].u=x;E[i].v=y;E[i].w=w;

}

qsort(E+1,m,sizeof(E[1]),cmp);

for(int i=1;i<=n;i++) T[i]=i;



int cnt=n,i=1;

while(cnt>1){

   //cout<<cnt<<endl;

   int fu=find(E[i].u),fv=find(E[i].v);

   if(fu!=fv) {

   // cout<<E[i].u<<'='<<E[i].v<<' '<<E[i].w<<endl;

       addedge(E[i].u,E[i].v,E[i].w);

       T[fu]=fv;cnt--;

   }

   i++;

}

Init();

for(int i=1;i<=q;i++){

    int x,y;

    scanf("%d %d",&x,&y);

    printf("%d\n",lca(x,y));

}

return 0;

}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末抹腿,一起剝皮案震驚了整個濱河市岛请,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌警绩,老刑警劉巖崇败,帶你破解...
    沈念sama閱讀 218,640評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異肩祥,居然都是意外死亡后室,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,254評論 3 395
  • 文/潘曉璐 我一進店門混狠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來岸霹,“玉大人,你說我怎么就攤上這事将饺」北埽” “怎么了?”我有些...
    開封第一講書人閱讀 165,011評論 0 355
  • 文/不壞的土叔 我叫張陵予弧,是天一觀的道長刮吧。 經(jīng)常有香客問我,道長掖蛤,這世上最難降的妖魔是什么杀捻? 我笑而不...
    開封第一講書人閱讀 58,755評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮蚓庭,結(jié)果婚禮上致讥,老公的妹妹穿的比我還像新娘仅仆。我一直安慰自己,他們只是感情好拄踪,可當我...
    茶點故事閱讀 67,774評論 6 392
  • 文/花漫 我一把揭開白布蝇恶。 她就那樣靜靜地躺著,像睡著了一般惶桐。 火紅的嫁衣襯著肌膚如雪撮弧。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,610評論 1 305
  • 那天姚糊,我揣著相機與錄音贿衍,去河邊找鬼。 笑死救恨,一個胖子當著我的面吹牛贸辈,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播肠槽,決...
    沈念sama閱讀 40,352評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼擎淤,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了秸仙?” 一聲冷哼從身側(cè)響起嘴拢,我...
    開封第一講書人閱讀 39,257評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎寂纪,沒想到半個月后席吴,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,717評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡捞蛋,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,894評論 3 336
  • 正文 我和宋清朗相戀三年孝冒,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片拟杉。...
    茶點故事閱讀 40,021評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡庄涡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出搬设,到底是詐尸還是另有隱情穴店,我是刑警寧澤,帶...
    沈念sama閱讀 35,735評論 5 346
  • 正文 年R本政府宣布焕梅,位于F島的核電站,受9級特大地震影響卦洽,放射性物質(zhì)發(fā)生泄漏贞言。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,354評論 3 330
  • 文/蒙蒙 一阀蒂、第九天 我趴在偏房一處隱蔽的房頂上張望该窗。 院中可真熱鬧弟蚀,春花似錦、人聲如沸酗失。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,936評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽规肴。三九已至捶闸,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間拖刃,已是汗流浹背删壮。 一陣腳步聲響...
    開封第一講書人閱讀 33,054評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留兑牡,地道東北人央碟。 一個月前我還...
    沈念sama閱讀 48,224評論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像均函,于是被迫代替她去往敵國和親亿虽。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,974評論 2 355

推薦閱讀更多精彩內(nèi)容