图论练习们~

Posted 一入OI深似海

tags:

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

/*
 hdu 1599 ( find the mincost route )  
Floyed求最小环
每个环一定是 由 i j k 构成
假设k是环中的max 要成环 就要保证不是链(md废话) 
利用Floyed的最外层循环含义 i-j最短路经过的点编号<k 
那个我们在 限制i<j<k 那么f[i][j]+g[i][k]+g[k][j]
一定能构成一个环 并且点数>=3 因为i j k 互不相同 
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 110
#define inf 2000000
using namespace std;
int n,m,f[maxn][maxn],g[maxn][maxn],ans;
void Clear(){
    for(int i=0;i<=n;i++)
        for(int j=0;j<=n;j++)
            f[i][j]=g[i][j]=inf;
    ans=inf;
}
int min(int x,int y){
    return x<y?x:y;
}
void Floyed(){
    for(int k=1;k<=n;k++){
        for(int i=1;i<k;i++)
            for(int j=i+1;j<k;j++)
                ans=min(ans,f[i][j]+g[i][k]+g[k][j]);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                f[i][j]=min(f[i][j],f[i][k]+f[k][j]);
    }
}
int main()
{
    while(~scanf("%d%d",&n,&m)){
        Clear();int u,v,t;
        for(int i=1;i<=m;i++){
            scanf("%d%d%d",&u,&v,&t);
            f[u][v]=min(f[u][v],t);
            f[v][u]=min(f[v][u],t);
            g[u][v]=g[v][u]=f[u][v];
        }
        Floyed();
        if(ans==inf)printf("It‘s impossible.\n");
        else printf("%d\n",ans);
    }
    return 0;
}
/*
hdu 2807 ( The Shortest Path )  
n*n判断矩阵相乘是不是等于另一矩阵
比较快的矩阵比较方法 get了 
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 81
#define inf 0x3f3f3f3f
using namespace std;
int n,m,Q,A[maxn][maxn],f[maxn][maxn],B[maxn];
struct node{
    int c[maxn][maxn];
}p[maxn];
void Clear(){
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            A[i][j]=0;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            f[i][j]=inf;    
}
void Insert(int x,int y){
    for(int i=1;i<=m;i++)B[i]=0;
    for(int i=1;i<=m;i++)
        for(int j=1;j<=m;j++)
            B[i]+=p[x].c[i][j]*A[y][j];
    int falg=0;
    for(int k=1;k<=n;k++){
        if(k==x||k==y)continue;
        falg=0;
        for(int i=1;i<=m;i++)
            if(A[k][i]!=B[i]){
                falg=1;break;
            }
        if(!falg)f[x][k]=1;
    }
}
void Floyed(){
    for(int k=1;k<=n;k++)
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                f[i][j]=min(f[i][j],f[i][k]+f[k][j]);
}
int main()
{
    while(1){
        scanf("%d%d",&n,&m);
        if(n==0&&m==0)break;
        Clear();int u,v;
        for(int k=1;k<=n;k++)
            for(int i=1;i<=m;i++)
                for(int j=1;j<=m;j++){
                    scanf("%d",&p[k].c[i][j]);
                    A[k][i]+=p[k].c[i][j]*j;
                }
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                Insert(i,j);
        Floyed();
        scanf("%d",&Q);
        while(Q--){
            scanf("%d%d",&u,&v);
            if(f[u][v]==inf)printf("Sorry\n");
            else printf("%d\n",f[u][v]);
        }
    }
    return 0;
}
/*
 hdu 2224 ( The shortest path ) 
不知道为啥出现在最短路分类里 我纯dp做的 
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define maxn 210
#define inf 0x3f3f3f3f
using namespace std;
int n;
double x[maxn],y[maxn],g[maxn][maxn],f[maxn][maxn],ans;
struct point{
    double x,y;
}p[maxn];
int cmp(const point &a,const point &b){
    return a.x<b.x;
}
void Clear(){
    for(int i=0;i<=n;i++)
        for(int j=0;j<=n;j++)
            f[i][j]=inf;
    for(int i=0;i<=n;i++)
        for(int j=0;j<=n;j++)
            g[i][j]=inf;
    ans=inf;
}
double Get(int i,int j){
    return sqrt((p[i].x-p[j].x)*(p[i].x-p[j].x)+(p[i].y-p[j].y)*(p[i].y-p[j].y));
}
int max(int a,int b){
    return a>b?a:b;
}
int main()
{
    while(scanf("%d",&n)!=EOF){
        Clear();
        for(int i=1;i<=n;i++)
            scanf("%lf%lf",&p[i].x,&p[i].y);
        sort(p+1,p+1+n,cmp);
        for(int i=1;i<=n;i++)
            for(int j=i+1;j<=n;j++)
                g[i][j]=g[j][i]=Get(i,j);
        f[1][1]=0;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++){
                int k=max(i,j)+1;
                f[i][k]=min(f[i][k],f[i][j]+g[j][k]);
                f[k][j]=min(f[k][j],f[i][j]+g[i][k]);
            }
        for(int i=1;i<=n;i++){
            ans=min(ans,f[i][n]+g[i][n]);
            ans=min(ans,f[n][i]+g[n][i]);
        }
        printf("%.2f\n",ans);
    }
    return 0;
    
}
/*
hdu  1598 ( find the most comfortable road )   
再次被分类坑了...
是并茶几不是最短路..
枚举每组数据所用的最小的边-最大的边
有点慢 不过还好并茶几飞快 
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 1010
using namespace std;
int n,m,Q,fa[maxn],mx;
struct node{
    int u,v,t;
    bool operator < (const node &a) const {
        return t<a.t;
    }
}e[maxn];
int init(){
    int x=0,f=1;char s=getchar();
    while(s<0||s>9){if(s==-)f=-1;s=getchar();}
    while(s>=0&&s<=9){x=x*10+s-0;s=getchar();}
    return x*f;
}
int find(int x){
    if(x!=fa[x])fa[x]=find(fa[x]);
    return fa[x];
}
int min(int x,int y){
    return x<y?x:y;
}
int main()
{
    while(~scanf("%d%d",&n,&m)){
        int u,v,t;
        for(int i=1;i<=m;i++){
            u=init();v=init();t=init();
            e[i].u=u;e[i].v=v;e[i].t=t;
        }
        sort(e+1,e+1+m);
        Q=init();
        while(Q--){
            u=init();v=init();mx=0x7fffffff;
            for(int k=1;k<=m;k++){
                for(int i=1;i<=n;i++)fa[i]=i;
                for(int i=k;i<=m;i++){
                    int r1=find(e[i].u);
                    int r2=find(e[i].v);
                    if(r1!=r2)fa[r2]=r1;
                    if(find(u)==find(v)){
                        mx=min(mx,e[i].t-e[k].t);break;
                    }
                }
            }
            if(mx==0x7fffffff)printf("-1\n");
            else printf("%d\n",mx);
        }
    }
    return 0;
}
/*+几条边不存在桥*/
#include<iostream>
#include<cstdio>
#include<stack>
#include<cstring>
#define maxn 1010
using namespace std;
int n,m,num,head[maxn],low[maxn],dfn[maxn],topt,f[maxn],r[maxn],sum,belong[maxn];
stack<int>s;
struct node{
    int v,pre;
}e[maxn*2];
int init(){
    int x=0,f=1;char s=getchar();
    while(s<0||s>9){if(s==-)f=-1;s=getchar();}
    while(s>=0&&s<=9){x=x*10+s-0;s=getchar();}
    return x*f;
}
void Clear(){
    num=0;topt=0;sum=0;
    for(int i=0;i<=n;i++)f[i]=0;
    for(int i=0;i<=n;i++)r[i]=0;
    for(int i=0;i<=n;i++)low[i]=0;
    for(int i=0;i<=n;i++)dfn[i]=0;
    for(int i=0;i<=n;i++)head[i]=-1;
    for(int i=0;i<=n;i++)belong[i]=0;
    while(!s.empty())s.pop();
}
void Add(int from,int to){
    e[num].v=to;
    e[num].pre=head[from];
    head[from]=num++;
}
void Dfs(int x,int from){
    low[x]=dfn[x]=++topt;
    f[x]=1;s.push(x);
    for(int i=head[x];i!=-1;i=e[i].pre){
        int v=e[i].v;
        if(i==(from^1))continue;
        if(dfn[v]==0){
            Dfs(v,i);low[x]=min(low[x],low[v]);
        }
        else if(f[v])low[x]=min(low[x],dfn[v]);
    }
    if(low[x]==dfn[x]){
        sum++;
        while(s.top()!=x){
            belong[s.top()]=sum;f[s.top()]=0;s.pop();
        }
        belong[s.top()]=sum;f[s.top()]=0;s.pop();
    }
}
int main()
{
    while(~scanf("%d%d",&n,&m)){
        Clear();int u,v;
        for(int i=1;i<=m;i++){
            u=init();v=init();
            Add(u,v);Add(v,u);
        }
        for(int i=1;i<=n;i++)
            if(dfn[i]==0)Dfs(i,-1);
        for(int u=1;u<=n;u++)
            for(int i=head[u];i!=-1;i=e[i].pre){
                int v=e[i].v;
                if(belong[u]!=belong[v])r[belong[u]]++;
            }
        int cnt=0;
        for(int i=1;i<=sum;i++)
            if(r[i]==1)cnt++;
        printf("%d\n",(cnt+1)/2);
    }
    return 0;
}
/*hdu 3768 ( Shopping )   SPFA+全排列*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define maxn 200010
using namespace std;
int T,n,m,k,c[20],num,head[maxn],dis[maxn],g[20][20],f[maxn],a[20];
long long ans;
struct node{
    int v,t,pre;
}e[maxn*10];
queue<int>q;
int init(){
    int x=0,f=1;char s=getchar();
    while(s<0||s>9){if(s==-)f=-1;s=getchar();}
    while(s>=0&&s<=9){x=x*10+s-0;s=getchar();}
    return x*f;
}
void Clear(){
    num=0;ans=0x7fffffff;
    memset(head,0,sizeof(head));
    memset(g,127/3,sizeof(g));
    memset(a,0,sizeof(a));
    memset(c,0,sizeof(c));
}
void Add(int from,int to,int dis){
    num++;e[num].v=to;
    e[num].t=dis;
    e[num].pre=head[from];
    head[from]=num;
}
void SPFA(int s){
    memset(dis,127/3,sizeof(dis));
    memset(f,0,sizeof(f));
    dis[s]=0;f[s]=1;q.push(s);
    while(!q.empty()){
        int u=q.front();
        f[u]=0;q.pop();
        for(int i=head[u];i;i=e[i].pre){
            int v=e[i].v;
            if(dis[v]>dis[u]+e[i].t){
                dis[v]=dis[u]+e[i].t;
                if(f[v]==0){
                    f[v]=1;q.push(v);
                }
            }
        }
    }
}
int main()
{
    T=init();
    while(T--){
        n=init();m=init();
        Clear();int u,v,t;
        for(int i=1;i<=m;i++){
            u=init();v=init();t=init();
            Add(u,v,t);Add(v,u,t);
        }
        k=init();
        for(int i=1;i<=k;i++){
            c[i]=init();a[i]=i;
        }
        SPFA(0);
        for(int i=1;i<=k;i++)
            g[0][i]=g[i][0]=dis[c[i]];
        for(int i=1;i<=k;i++){
            SPFA(c[i]);
            for(int j=1;j<=k;j++)
                g[i][j]=dis[c[j]];
        }
        do{
            long long mx=0;
            for(int i=1;i<=k+1;i++)
                mx+=g[a[i-1]][a[i]];
            ans=min(ans,mx);
        }while(next_permutation(a+1,a+k+1));
        cout<<ans<<endl;
    }
    return 0;
}
/*poj 1679 次小生成树n*n算法 get了*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 110
using namespace std;
int T,n,m,num,head[maxn],fa[maxn],c[maxn*maxn],mx[maxn][maxn],mst,ans;
struct node{
    int u,v,t,o;
    bool operator < (const node &x) const{
        return t<x.t;
    }
}p[maxn*maxn];
struct edge{
    int v,t,pre,x;
}e[maxn*maxn*2];
void Clear(){
    num=mst=0;ans=0x7fffffff;
    for(int i=0;i<=n;i++)fa[i]=i;
    for(int i=0;i<=n;i++)
        for(int j=0;j<=n;j++)
            mx[i][j]=0;
    for(int i=0;i<=m;i++)c[i]=0;
    for(int i=0;i<=n;i++)head[i]=0;
}
void Add(int from,int to,int dis,int numb){
    num++;e[num].v=to;
    e[num].t=dis;
    e[num].x=numb;
    e[num].pre=head[from];
    head[from]=num;
}
int find(int x){
    if(x!=fa[x])fa[x]=find(fa[x]);
    return fa[x];
}
void MST(){
    int tot=0;
    for(int i=1;i<=m;i++){
        int r1=find(p[i].u);
        int r2=find(p[i].v);
        if(r1!=r2){
            tot++;mst+=p[i].t;
            c[p[i].o]=1;fa[r2]=r1;
        }
        if(tot==n-1)break;
    }
}
void Dfs(int s,int now,int from,int mxx){
    mx[s][now]=mxx;
    for(int i=head[now];i;i=e[i].pre){
        int v=e[i].v;
        if(v==from)continue;
        if(c[e[i].x]==0)continue;
        Dfs(s,v,now,max(mxx,e[i].t));
    }
}
void Mx(){
    for(int i=1;i<=n;i++)
        Dfs(i,i,-1,0);
}
int main()
{
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&n,&m);
        Clear();int u,v,t;
        for(int i=1;i<=m;i++){
            scanf("%d%d%d",&u,&v,&t);
            Add(u,v,t,i);Add(v,u,t,i);
            p[i].u=u;p[i].v=v;
            p[i].t=t;p[i].o=i;
        }
        sort(p+1,p+1+m);
        MST();Mx();
        for(int i=1;i<=m;i++){
            if(c[p[i].o])continue;
            int len=mx[p[i].u][p[i].v];
            ans=min(ans,mst+p[i].t-len);
        }
        if(ans==mst)printf("Not Unique!\n");
        else printf("%d\n",mst);
    }
    return 0;
}

 

以上是关于图论练习们~的主要内容,如果未能解决你的问题,请参考以下文章

图论:TZOJ二分图练习

NOIP 考前 图论练习

图论_拓扑排序_练习1(优先队列小顶堆)

2021算法竞赛入门班第七节课图论练习题

NKOJ 2017信息学夏令营第1场(图论专项练习)

数据结构与算法—图论(广搜迷宫问题)