• POJ 树的直径和重心


    树的直径:(无根)树上最长两点间的最长路径,两次dfs即可,第一次dfs任选一点u,找到距离它最远的点s,再从点s进行一次dfs,找到距离s最远的点t,则s-t之间的路径就是树的直径。证明: <http://www.cnblogs.com/wuyiqi/archive/2012/04/08/2437424.html>

    poj2631 树的直径裸题

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<iostream>
    #include<vector>
    typedef long long ll;
    using namespace std;
    const int maxn=10005;
    ll d[maxn];
    struct KSD
    {
        int v,len,next;
    }g[maxn];
    int vis[maxn];
    int head[maxn],cnt;
    void add(int u,int v,int len){
        g[++cnt].v=v;
        g[cnt].next=head[u];
        g[cnt].len=len;
        head[u]=cnt;
    }
    void dfs(int x)
    {
        vis[x]=1;
        int i,v;
        for(i=head[x];i;i=g[i].next)
        {
            v=g[i].v;
            if(vis[v])continue;
            d[v]+=d[x]+g[i].len;
            dfs(v);
        }
        return ;
    }
    int main(){
        int a,b,c;int n=0;
        while(scanf("%d%d%d",&a,&b,&c)!=EOF){
    
            n=max(a,max(b,n));
            add(a,b,c);
            add(b,a,c);
    
        }
            d[1]=0;
            dfs(1);
            int m;
            ll s=0;
            for(int i=1;i<=n;i++){
                vis[i]=0;
                if(d[i]>s){
                    m=i;
                    s=d[i];
                }
                d[i]=0;
            }
            dfs(m);
            ll ans=0;
            for(int i=1;i<=n;i++)
                ans=max(ans,d[i]);
        printf("%lld
    ",ans);
    }
    

    poj1985 Cow Marathon 求树的直径裸题

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    const int maxn=200005;
    int n,m;
    struct P{
        int v,len,next;
    }g[maxn];
    
    int head[maxn],d[maxn],vis[maxn];
    int cnt=0;
    void add(int u,int v,int len){
        g[++cnt].v=v;
        g[cnt].next=head[u];
        g[cnt].len=len;
        head[u]=cnt;
    }
    void dfs(int x)
    {
        vis[x]=1;
        int i,v;
        for(i=head[x];i;i=g[i].next)
        {
            v=g[i].v;
            if(vis[v])continue;
            d[v]+=d[x]+g[i].len;
            dfs(v);
        }
        return ;
    }
    int main(){
        scanf("%d%d",&n,&m);
        int sum=0;
        for(int i=1;i<=n-1;i++){
            int x,y,z;
            char c;
            scanf("%d%d%d %c",&x,&y,&z,&c);
          //  cout<<c<<endl;
            add(x,y,z);
            add(y,x,z);
           // sum+=z;
        }
       // sum=sum*2;
            d[1]=0;
            dfs(1);
            int m;
            int s=0;
            for(int i=1;i<=n;i++){
                vis[i]=0;
                if(d[i]>s){
                    m=i;
                    s=d[i];
                }
                d[i]=0;
            }
            dfs(m);
            int ans=0;
            for(int i=1;i<=n;i++)
                ans=max(ans,d[i]);
          //  cout<<sum<<" "<<ans<<endl;
            printf("%d
    ",ans);
    }

    poj3310 Caterpillar

    给你一张无向图,问你这张图是否是一个Caterpillar,Caterpillar必须满足是一个连通图,无环,切存在一条路径,使图中所有的点距离该路径上点的最小距离为1或0

    易知改图是一棵树,首先并查集判断是否联通,先找到直径,再判断所有点距离直径距离

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    using namespace std;
    const int maxn=605;
    int fa[maxn],head[maxn],d[maxn],ans[maxn],vis[maxn];
    struct P{
        int v,len,next;
    }g[maxn*2];
    int  mp[maxn][maxn];
    int fi(int x){
        if(fa[x]==x)
            return x;
        return fa[x]=fi(fa[x]);
    }
    int cnt=0;
    void add(int u,int v){
        g[++cnt].v=v;
        g[cnt].next=head[u];
        head[u]=cnt;
    }
    void dfs(int x)
    {
        vis[x]=1;
        int i,v;
        for(i=head[x];i;i=g[i].next)
        {
            v=g[i].v;
            if(vis[v])continue;
            d[v]+=d[x]+1;
            dfs(v);
        }
        return ;
    }
    int n,m,p,q,k=0;
    bool DFS(int z){
        if(z==q){
            ans[z]=1;
            return true;
        }
        vis[z]=1;
        for(int i=head[z];i;i=g[i].next){
            int v=g[i].v;
            if(vis[v])
                continue;
            if(DFS(v)){
                ans[v]=1;
                return true;
            }
        }
        return false;
    }
    int main(){
        int cas=0;
        while(scanf("%d",&n)&&n!=0){
            for(int i=1;i<=n;i++){
                d[i]=vis[i]=ans[i]=head[i]=0;
                fa[i]=i;
                for(int j=1;j<=n;j++)
                    mp[i][j]=0;
            }
            scanf("%d",&m);
            bool f=1;
            if(m!=n-1)
                f=0;
            for(int i=1;i<=m;i++){
                int x,y;
                scanf("%d%d",&x,&y);
                mp[x][y]=mp[y][x]=1;
                x=fi(x);y=fi(y);
                if(x==y)
                    f=0;
                fa[x]=y;
                add(x,y);
                add(y,x);
            }
            for(int i=1;i<=n;i++)
            if(fi(i)!=fi(1)){
                f=0;
                break;
            }
            if(f==0){
                printf("Graph %d is not a caterpillar.
    ",++cas);
                continue;
            }
            dfs(1);
            int s=0;
            for(int i=1;i<=n;i++){
                vis[i]=0;
                if(d[i]>s){
                    p=i;
                    s=d[i];
                }
                d[i]=0;
            }
    
            dfs(p);
            s=0;
            for(int i=1;i<=n;i++){
                vis[i]=0;
                if(d[i]>s){
                    q=i;
                    s=d[i];
                }
                d[i]=0;
            }
    
            DFS(p);
            for(int i=1;i<=n;i++){
                int j=0;
                if(ans[i]==0){
                    for(j=1;j<=n;j++)
                    if(ans[j]==1){
                        if(mp[i][j]==1)
                            break;
                    }
                    if(j>n){
                        f=0;
                        break;
                    }
                }
    
            }
            if(f==0){
                  printf("Graph %d is not a caterpillar.
    ",++cas);
            }
            else   printf("Graph %d is a caterpillar.
    ",++cas);
    
        }
    }

    poj1849 Two

    大雪将城镇的街道覆盖了,两辆铲雪机从同一城市出发,要求将所有街道得雪都铲完,任意一辆铲雪机可以铲任意一条街道,最后两辆车可以停在任意一处,问两辆车的最少运动长度

    有些道路可以经过一次,但有些街道需要经过两次,那么即找到一条最长的距离,车子只要走一趟,易知这条路径即为直径,故答案为所有边的长度*2-直径

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    const int maxn=200005;
    int n,m;
    struct P{
        int v,len,next;
    }g[maxn];
    
    int head[maxn],d[maxn],vis[maxn];
    int cnt=0;
    void add(int u,int v,int len){
        g[++cnt].v=v;
        g[cnt].next=head[u];
        g[cnt].len=len;
        head[u]=cnt;
    }
    void dfs(int x)
    {
        vis[x]=1;
        int i,v;
        for(i=head[x];i;i=g[i].next)
        {
            v=g[i].v;
            if(vis[v])continue;
            d[v]+=d[x]+g[i].len;
            dfs(v);
        }
        return ;
    }
    int main(){
        scanf("%d%d",&n,&m);
        int sum=0;
        for(int i=1;i<=n-1;i++){
            int x,y,z;
            scanf("%d%d%d",&x,&y,&z);
            add(x,y,z);
            add(y,x,z);
            sum+=z;
        }
        sum=sum*2;
            d[1]=0;
            dfs(1);
            int m;
            int s=0;
            for(int i=1;i<=n;i++){
                vis[i]=0;
                if(d[i]>s){
                    m=i;
                    s=d[i];
                }
                d[i]=0;
            }
            dfs(m);
            int ans=0;
            for(int i=1;i<=n;i++)
                ans=max(ans,d[i]);
          //  cout<<sum<<" "<<ans<<endl;
            printf("%d
    ",sum-ans);
    }

    poj3099 Go Go Gorelians

    给你一张图,已知两两之间的距离为1,问你找出使距离某个点最远距离最小的点,即找到直径,若直径上的点为奇数,则为中间的,若为偶数,则为中间两个,注意输入给的距离是让我们建树的

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    
    const int maxn=10005;
    int vis[maxn],head[maxn],cnt,v0[maxn];
    struct P{
        int v,next;
      //  double len;
    }g[maxn];
    struct Q{
        int i,x,y,z;
    }p[maxn];
    int d[maxn],ans[maxn];
    //int sum=0;
    void add(int u,int v){
        g[++cnt].v=v;
       // g[cnt].len=len;
        g[cnt].next=head[u];
        head[u]=cnt;
    }
    int ma;  int n;
    
    void dfs(int x)
    {
        vis[x]=1;
        int i,v;
        for(i=head[x];i;i=g[i].next)
        {
            v=g[i].v;
            if(vis[v])continue;
            d[v]+=d[x]+1;
            dfs(v);
        }
        return ;
    }
    int q;
    int l;
    bool DFS(int z){
        if(z==q){
            return true;
        }
        vis[z]=1;
        for(int i=head[z];i;i=g[i].next){
            int v=g[i].v;
            if(vis[v])
                continue;
            if(DFS(v)){
                ans[++l]=v;
                return true;
            }
        }
        return false;
    }
    int main(){
    
        int c=0;
        while(scanf("%d",&n)&&n!=0){
            l=0;
            ma=1e7;
            for(int i=1;i<=1000;i++)
              vis[i]=head[i]=ans[i]=d[i]=0;
            c=0;
            cnt=0;
            for(int i=1;i<=n;i++){
                scanf("%d%d%d%d",&p[i].i,&p[i].x,&p[i].y,&p[i].z);
                v0[++c]=p[i].i;
            }
            for(int i=2;i<=n;i++){
                int s=1e9;
                int t;
                for(int j=1;j<i;j++){
                    int o=(p[i].x-p[j].x)*(p[i].x-p[j].x)+(p[i].y-p[j].y)*(p[i].y-p[j].y)+(p[i].z-p[j].z)*(p[i].z-p[j].z);
                    if(o<s){
                        s=o;
                        t=p[j].i;
                    }
                }
                add(t,p[i].i);
                add(p[i].i,t);
           
            }
            dfs(v0[1]);
            int c;
            int s=0;
            for(int i=1;i<=n;i++){
                int k=v0[i];
                vis[k]=0;
                if(d[k]>s){
                    c=k;
                    s=d[k];
                }
                d[k]=0;
            }
    
            dfs(c);
            s=0;
            for(int i=1;i<=n;i++){
                int k=v0[i];
                vis[k]=0;
                if(d[k]>s){
                    q=k;
                    s=d[k];
                }
                d[k]=0;
            }
    
            DFS(c);
           ans[++l]=c;
         if(l%2==0){
            cout<<min(ans[l/2+1],ans[l/2])<<" "<<max(ans[l/2+1],ans[l/2])<<endl;
         }
         else printf("%d
    ",ans[l/2+1]);
        }
    }
    

      

    树的重心:如果存在某个节点,其所有子树中最大节点的子树最小,则该节点为树的重心;任选一个点作为根,进行dfs,记录某个节点的子节点数,则满足max(n-son[u]-1,sou[v])取最小的节点u即为树的重心(v为u的子节点);

    poj3107 Goldfather

    树的重心裸题

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int maxn=100005;
    int cnt,d[maxn],vis[maxn],head[maxn],ans[maxn];
    struct P{
        int v,next;
    }g[maxn];
    void add(int u,int v){
        g[++cnt].v=v;
        g[cnt].next=head[u];
        head[u]=cnt;
    }
    int ma=1e9;
    int n;
    void dfs(int u){
        int sum=0;
        d[u]=1;
        vis[u]=1;
        for(int i=head[u];i;i=g[i].next){
            int v=g[i].v;
            if(vis[v])
                continue;
            dfs(v);
            d[u]+=d[v];
            if(d[v]>=ans[u])
                ans[u]=d[v];
        }
        if(n-d[u]>ans[u])
        ans[u]=n-d[u];
        if(ma>ans[u])
        ma=ans[u];
    }
    int main(){
            cnt=0;
    
            scanf("%d",&n);
            for(int i=1;i<=n;i++){
                head[i]=d[i]=vis[i]=0;
            }
            for(int i=1;i<n;i++){
                int u,v;
                scanf("%d%d",&u,&v);
                add(u,v);
                add(v,u);
            }
            dfs(1);
            for(int i=1;i<=n;i++){
                if(ans[i]==ma)
                printf("%d ",i);
            }
            printf("
    ");
    }

    poj1655 Banlancing Act

    求树的重心,输出字典序最小的

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int maxn=100005;
    int cnt,d[maxn],vis[maxn],head[maxn];
    struct P{
        int v,next;
    }g[maxn];
    void add(int u,int v){
        g[++cnt].v=v;
        g[cnt].next=head[u];
        head[u]=cnt;
    }
    int ans1,ans2;
    int n;
    void dfs(int u){
        int sum=0;
        d[u]=1;
        vis[u]=1;
        for(int i=head[u];i;i=g[i].next){
            int v=g[i].v;
            if(vis[v])
                continue;
            dfs(v);
            d[u]+=d[v];
            sum=max(sum,d[v]);
        }
        sum=max(sum,n-d[u]);
        if((sum<ans2)||(sum==ans2&&u<ans1)){
            ans1=u;
            ans2=sum;
        }
    
    }
    int main(){
        int t;
        scanf("%d",&t);
        while(t--){
            cnt=0;
            ans1=1e8;
            ans2=1e8;
            scanf("%d",&n);
            for(int i=1;i<=n;i++){
                head[i]=d[i]=vis[i]=0;
            }
            for(int i=1;i<n;i++){
                int u,v;
                scanf("%d%d",&u,&v);
                add(u,v);
                add(v,u);
            }
            dfs(1);
            printf("%d %d
    ",ans1,ans2);
        }
    }
    

      

  • 相关阅读:
    Toggle控制窗口的显隐
    碰撞检测(2D&&3D)
    3D空间 圆柱体画线
    鼠标拖动2D物体(图片)
    实现图片的闪烁效果
    UI 2D图片随鼠标旋转
    射线检测(Summary)
    [转]C#静态方法与非静态方法的比较
    获取精灵
    用于切割字符串的方法
  • 原文地址:https://www.cnblogs.com/dlutjwh/p/10987787.html
Copyright © 2020-2023  润新知