• 洛谷练习P2279 P1346


    题目描述

    2020年,人类在火星上建立了一个庞大的基地群,总共有n个基地。起初为了节约材料,人类只修建了n-1条道路来连接这些基地,并且每两个基地都能够通过道路到达,所以所有的基地形成了一个巨大的树状结构。如果基地A到基地B至少要经过d条道路的话,我们称基地A到基地B的距离为d。

    由于火星上非常干燥,经常引发火灾,人类决定在火星上修建若干个消防局。消防局只能修建在基地里,每个消防局有能力扑灭与它距离不超过2的基地的火灾。

    你的任务是计算至少要修建多少个消防局才能够确保火星上所有的基地在发生火灾时,消防队有能力及时扑灭火灾。

    输入输出格式

    输入格式:

    输入文件名为input.txt。

    输入文件的第一行为n (n<=1000),表示火星上基地的数目。接下来的n-1行每行有一个正整数,其中文件第i行的正整数为a[i],表示从编号为i的基地到编号为a[i]的基地之间有一条道路,为了更加简洁的描述树状结构的基地群,有a[i]<i。

    输出格式:

    输出文件名为output.txt

    输出文件仅有一个正整数,表示至少要设立多少个消防局才有能力及时扑灭任何基地发生的火灾。

    输入输出样例

    输入样例#1:
    6
    1
    2
    3
    4
    5
    
    输出样例#1:
    2

    http://www.cnblogs.com/candy99/p/6006145.html
    简化版

    问题在于不用考虑根节点一定是了
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <queue>
    using namespace std;
    const int N=1005;
    inline int read(){
        char c=getchar();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
        return x*f;
    }
    int n,v;
    struct edge{
        int v,ne;
    }e[N<<1];
    int h[N],cnt=0;
    void ins(int u,int v){
        cnt++;
        e[cnt].v=v;e[cnt].ne=h[u];h[u]=cnt;
        cnt++;
        e[cnt].v=u;e[cnt].ne=h[v];h[v]=cnt;
    }
    struct node{
        int u,d;
        node(int a=0,int b=0):u(a),d(b){}
        bool operator <(const node &r)const{return d>r.d;}
    };
    node lst[N];int p=0;
    int d[N],fa[N],q[N],head,tail;
    void bfs(int s){
        memset(d,-1,sizeof(d));
        p=0;
        head=1;tail=0;
        q[++tail]=s; d[s]=0; fa[s]=0;
        while(head<=tail){
            int u=q[head++],child=0;
            for(int i=h[u];i;i=e[i].ne){
                int v=e[i].v;
                if(d[v]==-1){child++;
                    d[v]=d[u]+1;
                    fa[v]=u;
                    q[++tail]=v;
                }
            }
            lst[++p]=node(u,d[u]);
        }
    }
    int vis[N];
    void dfs(int u,int fa,int d){//printf("dfs %d %d
    ",u,d);
        vis[u]=1;
        for(int i=h[u];i;i=e[i].ne){
            int v=e[i].v;
            if(v!=fa&&d<2) dfs(v,u,d+1);
        }
    }
    int main(int argc, const char * argv[]) {
            n=read();
            for(int i=1;i<=n-1;i++){v=read();ins(i+1,v);}
            
            bfs(1);
            sort(lst+1,lst+1+p);
            int ans=0;
            for(int i=1;i<=p;i++){//except s
                int u=lst[i].u;//printf("u %d
    ",u);
                if(vis[u]) continue;
                for(int j=1;j<=2;j++) u=fa[u];
                dfs(u,0,0);
                ans++;
            }
            printf("%d
    ",ans);
        
        
        return 0;
    }



    题目描述

    在一个神奇的小镇上有着一个特别的电车网络,它由一些路口和轨道组成,每个路口都连接着若干个轨道,每个轨道都通向一个路口(不排除有的观光轨道转一圈后返回路口的可能)。在每个路口,都有一个开关决定着出去的轨道,每个开关都有一个默认的状态,每辆电车行驶到路口之后,只能从开关所指向的轨道出去,如果电车司机想走另一个轨道,他就必须下车切换开关的状态。

    为了行驶向目标地点,电车司机不得不经常下车来切换开关,于是,他们想请你写一个程序,计算一辆从路口A到路口B最少需要下车切换几次开关。

    输入输出格式

    输入格式:

    第一行有3个整数2<=N<=100,1<=A,B<=N,分别表示路口的数量,和电车的起点,终点。

    接下来有N行,每行的开头有一个数字Ki(0<=Ki<=N-1),表示这个路口与Ki条轨道相连,接下来有Ki个数字表示每条轨道所通向的路口,开关默认指向第一个数字表示的轨道。

    输出格式:

    输出文件只有一个数字,表示从A到B所需的最少的切换开关次数,若无法从A前往B,输出-1。

    输入输出样例

    输入样例#1:
    3 2 1
    2 2 3
    2 3 1
    2 1 2
    输出样例#1:
    0
     

    超水最短路一遍AC
    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    const int N=105,INF=1e9+5;
    inline int read(){
        char c=getchar();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    int n,s,v,st,ed;
    struct edge{
        int v,w,ne;
    }e[N*N<<1];
    int h[N],cnt=0;
    inline void ins(int u,int v,int w){
        cnt++;
        e[cnt].v=v;e[cnt].w=w;e[cnt].ne=h[u];h[u]=cnt;
    }
    int q[N],head=1,tail=1;
    inline void lop(int &x){if(x==N) x=1;}
    int d[N],inq[N];
    void spfa(){
        for(int i=1;i<=n;i++) d[i]=INF;
        d[st]=0;
        head=tail=1;
        memset(inq,0,sizeof(inq));
        q[tail++]=st; inq[st]=1;
        while(head!=tail){
            int u=q[head++];inq[u]=0;lop(head);
            for(int i=h[u];i;i=e[i].ne){
                int v=e[i].v,w=e[i].w;
                if(d[v]>d[u]+w){
                    d[v]=d[u]+w;
                    if(!inq[v]){q[tail++]=v;inq[v]=1;lop(tail);}
                }
            }
        }
    }
    
    int main(){
        n=read();st=read();ed=read();
        for(int i=1;i<=n;i++){
            s=read();
            for(int j=1;j<=s;j++){
                if(j==1) ins(i,read(),0);
                else ins(i,read(),1);
            }
        }
        spfa();
        if(d[ed]==INF) puts("-1");
        else printf("%d",d[ed]);
    }
     
  • 相关阅读:
    【SQL Server学习笔记】Service Broker创建异步的、数据驱动的消息应用程序
    记录几句不错的话
    DBA最缺的不是技术
    小数点引起的数据类型转换问题
    hdu 3062 2SAT最基础题
    POJ 1679 判断最小生成树是否唯一
    POJ 1459 构图+最大流(Edmond_karp模版)
    POJ 3522 最大边与最小边差值最小的生成树
    POJ 1659 根据度序列构图
    POJ 1273 求最大流(Edmond_karp模板题)
  • 原文地址:https://www.cnblogs.com/candy99/p/6062025.html
Copyright © 2020-2023  润新知