PPOJ刷题-2

Posted Mr.wu123

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PPOJ刷题-2相关的知识,希望对你有一定的参考价值。

PPOJ刷题-2

1118: 继续畅通工程(kruskal)

题目描述

省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可)。现得到城镇道路统计表,表中列出了任意两城镇间修建道路的费用,以及该道路是否已经修通的状态。现请你编写程序,计算出全省畅通需要的最低成本。

输入

Input

测试输入包含若干测试用例。每个测试用例的第1行给出村庄数目N ( 1< N < 100 );随后的 N(N-1)/2 行对应村庄间道路的成本及修建状态,每行给4个正整数,分别是两个村庄的编号(从1编号到N),此两村庄间道路的成本,以及修建状态:1表示已建,0表示未建。
当N为0时输入结束。

输出

每个测试用例的输出占一行,输出全省畅通需要的最低成本。

样例输入

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

样例输出

3
1
0
#include<bits/stdc++.h>
using namespace std;
const int N=105;

struct Edge
   int s,e,len;
edge[N*(N-1)/2];

int n,m,father[N];//分别表示点数,边数,和并查集情况
int findfd(int x)

    if(father[x]==x)
        return x;
    return findfd(father[x]);


int cmp(Edge a,Edge b)//按照边长进行排序

    return a.len<b.len;


int Kruskal(int m)

    sort(edge+1,edge+m+1,cmp);//对边进行排序
    int cost=0;
    for(int i=1;i<=m;i++)//边数刚好构成最小生成树
        int x=findfd(edge[i].s);
        int y=findfd(edge[i].e);
        if(x!=y)
            father[x]=y;
            cost+=edge[i].len;
        
    
    return cost;


int main()

    while(cin>>n&&n)
        for(int i=1;i<=n;i++)
            father[i]=i;
        m=n*(n-1)/2;
        for(int i=1;i<=m;i++)
            int c,d;
            cin>>edge[i].s>>edge[i].e>>c>>d;
            if(!d) edge[i].len=c;
            else edge[i].len=0;
        
        printf("%d\\n",Kruskal(m));
    
    return 0;

1138: N皇后问题(DFS)

题目描述

在一个N*N的棋盘上,问你有多少不同的方式摆放N个皇后。
每个皇后所处的行、列、两条对角线上都不能有其他皇后。

输入

无需处理到EOF
一个整数N,3<=N<=13

输出

输出不同的方案数

样例输入

4

样例输出

2
#include<bits/stdc++.h>
using namespace std;

int col[32],r[32],l[32];//分别标记行,主对角线和副对角线
int n,ans=0;

void DFS(int row)//每行遍历

    if(row==n+1)
        ans++;
        return;
    
    for(int i=1;i<=n;i++)
        if(!col[i]&&!r[i-row+n]&&!l[i+row])//+n是防止数组越界
        
            col[i]=r[i-row+n]=l[i+row]=1;
            DFS(row+1);
            col[i]=r[i-row+n]=l[i+row]=0;
        
    


int main()

    cin>>n;
    DFS(1);
    cout<<ans<<endl;
    return 0;

1286: PIPI运货(Floyd)

题目描述

PIPI是一个商人,经常需要将货物从A地运到B地,我们可以把PIPI经常活动的区域抽象成一个n个结点的地图,用一个nxn的矩阵表示。
矩阵第i行第j列的值代表PIPI从 i 地将货物运到 j 地所需要的固定费用,若该值为-1则代表 i 和 j之间没有直接的通路,注意道路是双向的。
除了上述固定费用外,PIPI在经过每一个结点时都需要交一次过路费(起点和终点不需要交过路费)。
作为一个精打细算的商人,你能帮PIPI计算出从A地到B地的最少费用是多少吗?

输入

第一行输入结点数目n (0<n<=100)
接下来n行输入一个nxn的矩阵(矩阵的值不大于1000)。
第n+2行输入n个数,代表每个结点的过路费cost(cost<=1000)。
第n+3行输入一个数q (q<=10000),代表PIPI的询问次数。
接下来q行,每行输入两个数字,询问A到B的最少花费。

输出

输出q个数字,代表q次询问的结果。若询问的两个地点不可达,输出-1.

样例输入

5
0 3 22 -1 4
3 0 5 -1 -1
22 5 0 9 20
-1 -1 9 0 4
4 -1 20 4 0
5 17 8 3 1
3
1 3
3 5
2 4

样例输出

21
16
17
#include<bits/stdc++.h>
using namespace std;
const int INF=1e8;

int R[102][102],C[102];

int main()

    int n;
    cin>>n;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            int k;
            cin>>k;
            R[i][j]=(k==-1?INF:k);
        
    
    for(int j=1;j<=n;j++)
        cin>>C[j];
    for(int k=1;k<=n;k++)//其中的k表示i->j中所经过的点,如果路径长度小就更新
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                if(R[i][k]+R[k][j]+C[k]<R[i][j])
                    R[i][j]=R[i][k]+R[k][j]+C[k];
            
        
    
    int m;
    cin>>m;
    while(m--)
        int x,y;
        cin>>x>>y;
        cout<<R[x][y]<<endl;
    
    return 0;

1304: 盗窃团伙(Floyd)

题目描述

美丽祥和的CSU校园里有许多门面,每个门面都出租给做生意的商户,商户之间都在做着各自的生意。但是在宁静的校园里也会有邪恶势力存在。CSU存在着一个盗窃团伙麓石开,盗窃团伙为首的是鸡腿xiefang,他们总是想着如何去盗窃所有门面商户的商品,然后疯狂的盗取别人的劳动成果。

现在给定n个门面的路线图,若门面i和门面j有一条直接通路,那么在图里面我们用一条无向边来表示i和j可达,边上的权值是门面i和门面j的道路长度。现在鸡腿和xiefang准备在n个门面中选定一个门面租赁,便于偷窃其他所有门面的商品,所以他们对租赁门面的要求是,距离他们租赁门面最远的门面到该门面的路程最短。试问他们应该租赁哪一个门面。

输入

输入第一行包括两个数字n和m , 分别代表CSU的门面数目和门面之间的路径数目( n<=500 m <=10000)。
接下来m行每行输入三个数字 u v w ,代表门面u和门面v之间的距离是w。(1<=u,v <=n , 1<=w <=1000)

输出

输出他们会租赁的门面和与该门面相距最远门面的距离,若有多个合法门面,则输出编号最小的那一个。若他们无法偷窃所有的门面,输出"What a pity!"

样例输入

3 3
1 2 3
1 3 4
2 3 1

样例输出

2 3
#include<bits/stdc++.h>
using namespace std;
const int INF=1e9;

int mp[505][505],fa[505],n,m;

int find_F(int x)
   if(fa[x]!=x)
    fa[x]=find_F(fa[x]);
   return fa[x];


void Floyd()
   for(int k=1;k<=n;k++)
      for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            if(mp[i][k]+mp[k][j]<mp[i][j])
                mp[i][j]=mp[i][k]+mp[k][j];
        
      
   


void solve()

    Floyd();
    int center_ans=1,Ans=INF;
    for(int center=1;center<=n;center++)//查找一点到某一点的最远的最小距离
        int MaxDis=0;
        for(int j=1;j<=n;j++)
            MaxDis=max(MaxDis,mp[center][j]);
        
        if(Ans>MaxDis)
            Ans=min(Ans,MaxDis);
            center_ans=center;
        
    
    printf("%d %d\\n",center_ans,Ans);


int main()

    cin>>n>>m;
    for(int i=1;i<=n;i++)
        fa[i]=i;
        for(int j=1;j<=n;j++)
            mp[i][j]=(i==j?0:INF);
        
    
    for(int i=1;i<=m;i++)
        int x,y,c;
        cin>>x>>y>>c;
        mp[x][y]=mp[y][x]=c;
        if(find_F(x)!=find_F(y))
            fa[x]=fa[y];
    
    int cnt=0;
    for(int i=1;i<=n;i++)
        if(fa[i]==i) cnt++;
    if(cnt>1)
        printf("What a pity!\\n");
    else
        solve();
    return 0;

1306: 盗窃团伙II(Kruskal)

题目描述

听说PIPI家又有新产品了,盗窃团伙麓石开鸡腿xiefang开始计划着要去PIPI家偷产品了。要是偷到了,他们就可以把PIPI家的产品理不直气也壮高价售出了!!!
CSU的地下有二战时构建的地下交通网络,交通网络中有n个枢纽,m条隧道,每个隧道都连接了两个交通枢纽。麓石开团伙在 1 号枢纽,而PIPI家的产品中心刚好位于n号枢纽,现在他们准备从地下隧道直通PIPI家的产品中心。但是这些隧道已经年久失修,需要翻新一遍才能够安全通过。现在麓石开想请若干家施工公司将其中的一些隧道翻新,使得他们能够从 1 号枢纽走到 n 号枢纽。这些施工公司能够同时开工翻新隧道,但是每一家公司都只能翻新一条隧道。 (两个枢纽之间可能有多条隧道)
麓石开只想着尽可能早一点的偷到PIPI家的新产品,请问至少需要多少天,他们才能够修通隧道,进入PIPI家的产品中心偷产品??

输入

输入的第一行包含两个整数n, m,用一个空格分隔,分别表示交通枢纽的数量和候选隧道的数量 (n<=1e5 , m<=2e5)。
第2行到第m+1行,每行包含三个整数a, b, c,表示枢纽a和枢纽b之间可以修建一条隧道,需要的时间为c天 (1<=a,b<=n , 0<c<=1e5)。

输出

输出盗窃团伙至少需要多少天才能偷到PIPI家的产品?若PIPI足够幸运,让他们没有办法偷到产品,则输出"How lucky!"

样例输入

6 6
1 2 4
2 3 4
3 6 7
1 4 2
4 5 5
5 6 6

样例输出

6

提示

然鹅PIPI并没有 How lucky 的时候 ,o(╥﹏╥)o

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int fa[N],n,m;
struct edge
    int s,e,c;
s[2*N];

int cmp(edge a,edge b)

    return a.c<b.c;


int find_f(int x)//压缩版并查集

    return fa[x]==x?x:fa[x]=find_f(fa[x]);


int Kruskal()
    sort(s,s+m,cmp);
    for(int i=0;i<m;i++)

        if(find_f(s[i].s)!=find_f(s[i].e))
            fa[find_f(s[i].s)]=find_f(s[i].e);
        
        if(find_f(1)==find_f(n))//找到最少修建好1到n所需的时间
            return s[i].c;
        //因为是从小到大排序,如果1到n所需时间短就会马上输出
        //如果所需时间长,在构建最小生成树的过程中就会输出
        //不管如何所需最少时间都是此刻所连接了1到n的路径时间
    
    return -1;


int main()

    cin>>n>>m;
    for(int i=1;i<=n;i++)
        fa[i]=i;
    for(int i=0;i<m;i++)
        cin>>s[i].s>>s[i].e>>s[i].c;
    
    int ans=Kruskal();
    if(ans==-1)
        printf("How lucky!\\n");
    else
        printf("%d\\n",ans);
    return 0;

1337: 汉诺塔问题(递归)

题目描述

假设有三个分别命名为A、B和C的塔座,在塔座X上插有n个直径大小各不相同、依小到大编号为1,2,…,n的圆盘。现要求将A轴上的n个圆盘移至塔座C上并仍按同样顺序叠排,圆盘移动时必须遵循下列规则:

1)每次只能移动一个圆盘;

2)圆盘可以插在A、B和C中的任一塔座上;

3)任何时刻都不能将一个较大的圆盘压在较小的圆盘之上。

输入

输入包含多组测试用例。
每组样例输入一个正整数n (n<=15)

输出

对于每组测试样例,输出每一步如何进行移动。

样例输入

1
2
3

样例输出

Move disk 1 from A to C

Move disk 1 from A to B
Move disk 2 from A to C
Move disk 1 from B to C

Move disk 1 from A to C
Move disk 2 from A to B
Move disk 1 from C to B
Move disk 3 from A to C
Move disk 1 from B to A
Move disk 2 from B to C
Move disk 1 from A to C
#include<bits/stdc++.h>
using namespace std;
int n;

void Move(char x,int n,char y)
   printf("Move disk %d from %c to %c\\n",n,x,y);


void hanoi(int n,char x,char y, char z)

    if(n==1) Move(x,1,z);
    else 
        hanoi(n-1,x,z,y);//先将上面n-1个小盘子从A柱经过C柱放到B柱上
        Move(x,n,z);//将最底层的盘子从A柱放到C柱
        hanoi(n-1,y,x,z);//将剩下的n-1个盘子从B柱经过A柱放到C柱
    


int main()

    while(cin>>n)
       hanoi(n,'A','B','C');
       printf("\\n");
    
    return 0;

1273: 三个有序数组的交集

题目描述

现在有三个有序数组 A , B ,C ,请你求出他们的交集。

输入

第一行输入三个正整数 n , m , q 表示三个有序数组的大小 (1<=n,m,q<=1e5)。
第二行输入数组A。
第三行输入数组B。
第四行输入数组C。

输出

输出一行,表示他们的交集,元素之间以空格分割。

样例输入

5 5 5
1 2 3 4 5
1 2 5 7 9
1 3 4 5 8

样例输出

1 5
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;

int main()

    //i、j、k分别为遍历三个数组的指针,x为指向元素的最小值
    int i,j,k;
    int x,n,m,q;
    int A[N],B[N],C[N];
    cin>>n>>m>>q;
    for(i=0;i<n;i++)
        cin>>A[i];
    for(i&#

以上是关于PPOJ刷题-2的主要内容,如果未能解决你的问题,请参考以下文章

PPOJ刷题-2

PPOJ刷题-1

PPOJ刷题-1

PPOJ刷题-1

PPOJ刷题-3

刷题95—树