图论刷水题记录(一)(最短路-----dijkstra算法)

最近实在不知道干些什么,感觉自己除了水题什么都不会做,算了去刷一刷图论的水题吧本来想合起来一起发,想了想太长的话以后看起来也不方便,题目所以今天晚上就先发了dij部分,由上到下由易变难。

1.POJ 2387 Til the Cows Come Home(优先队列优化+邻接表)
2.poj 1502 (最短路)
3.POJ3268-Silver Cow Party-(优先队列优化+邻接表)
4.poj 1511 Invitation Cards(优先队列+dij+链向式前向星存图)
5.Heavy Transportation POJ - 1797(优先队列优化+邻接表)
6.poj2253(dij变形+优先队列)
7.hdu4725The Shortest Path in Nya Graph(建图建图建图+dij+优先队列优化)
dijk部分:
3月23日
1.POJ 2387 Til the Cows Come Home

很典型的板子题,问从1点到n点的最小花费(使用优先队列进行优化)

#pragma GCC optimize(3,"Ofast","inline")
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define maxn  2010
//#define true false
//#define false true
const int MaxN = 0x3f3f3f3f;
const int MinN = 0xc0c0c00c;
const double pi = acos(-1);
typedef long long ll;
const int mod = 1e9 + 7;
using namespace std;

int t,n;
bool visited[maxn];
int dis[maxn];

struct wazxy{
    int v,val;
    wazxy(int v1,int e1){v=v1;val=e1;}
};
vector<wazxy> a[maxn];
struct node{
    int id,dis;
    node(int a,int b){id=a,dis=b;}
    bool operator < (const node & a)const
    {return dis>a.dis;}
};

void dij(){
    int s=1;
    dis[s]=0;
    priority_queue<node>q;
    q.push(node(s,dis[s]));
    while(!q.empty()){
        node temp=q.top();
        q.pop();
        if(visited[temp.id])  continue;
        visited[temp.id]=true;
        for(int i=0;i<a[temp.id].size();i++){
            wazxy node1=a[temp.id][i];
            if(visited[node1.v]) continue;
            if(dis[node1.v]>node1.val+temp.dis){
                dis[node1.v]=node1.val+temp.dis;
                q.push(node(node1.v,dis[node1.v]));
            }
        }
    }
    printf("%d",dis[n]);
}

int main()
{
    cin>>t>>n;
    memset(visited,false,sizeof(visited));
    memset(dis,MaxN,sizeof(dis));
    while(t--){
        int x,y,v;
        scanf("%d%d%d",&x,&y,&v);
        a[x].push_back(wazxy(y,v));
        a[y].push_back(wazxy(x,v));
    }
    dij();
    return 0;
}

3月24号
2.poj 1502 (最短路)

题目很坑爹:大致意思是从起点找出到每个点的最短距离,然后从到每个点的最短距离中找出一个最大值输出
找了一下午的bug,原因竟然是再一次的忘记调用dij函数md

#pragma GCC optimize(3,"Ofast","inline")
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define maxn  110
//#define true false
//#define false true
const int MaxN = 0x3f3f3f3f;
const int MinN = 0xc0c0c00c;
const double pi = acos(-1);
typedef long long ll;
const int mod = 1e9 + 7;
using namespace std;
int n;
int maps[maxn][maxn];
int visited[maxn],dis[maxn];
void init(){
    memset(maps,MaxN,sizeof(maps));
    for(int i=0;i<maxn;i++) maps[i][i]=0;
}
void dij(){
     memset(visited,false,sizeof(visited));
     for(int i=1;i<=n;i++) dis[i]=maps[1][i];
     for(int i=1;i<=n;i++){
        int imin=MaxN,x;
        for(int f=1;f<=n;f++){
            if(!visited[f]&&dis[f]<=imin){
                x=f;
                imin=dis[f];
            }
        }
        visited[x]=true;
        for(int f=1;f<=n;f++){
            if(!visited[f]&&dis[f]>dis[x]+maps[x][f]){
                dis[f]=dis[x]+maps[x][f];
            }
        }
     }
}
int main()
{
    char a[10];
    while(scanf("%d",&n)!=EOF){
        init();
        for(int i=2;i<=n;i++){
            for(int j=1;j<i;j++){
                scanf("%s",a);
                if(a[0]!='x') maps[i][j]=maps[j][i]=atoi(a);
            }
        }
    }
//    for(int i=1;i<=n;i++){
//        for(int f=1;f<=n;f++){
//            cout<
//        }
//        cout<
//    }
    int imax=0;
    dij();
    for(int i=1;i<=n;i++){
        imax=max(imax,dis[i]);
//        cout<
    }
    cout<<imax<<endl;
    return 0;
}

3.POJ3268-Silver Cow Party-(Dijstra)
题目大意:让你求每个点到某个点x距离的最短路+x点在返回原点路径的最短路之和,找出其中和的最大值
dij+了队列优化才险些过去(735ms)

#pragma GCC optimize(3,"Ofast","inline")
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define maxn  1010
//#define true false
//#define false true
const int MaxN = 0x3f3f3f3f;
const int MinN = 0xc0c0c00c;
const double pi = acos(-1);
typedef long long ll;
const int mod = 1e9 + 7;
using namespace std;
struct rule{
    int u,v,cost;
    rule(int a,int b,int c){u=a,v=b,cost=c;}
};
int dis[maxn];
bool visited[maxn];
int n,m,k;
int sum[maxn];
vector <vector<rule> > a;
struct node{
    int n,dis;
    node(int a,int b){n=a,dis=b;}
    bool operator < (const node & a)const
    {return dis>a.dis;}
};
void init(){
    a.resize(maxn);
    memset(visited,false,sizeof(visited));
    memset(dis,MaxN,sizeof(dis));
}

void dij(int x){
    memset(visited,false,sizeof(visited));
    memset(dis,MaxN,sizeof(dis));
    dis[x]=0;
    priority_queue<node> q;
    q.push(node(x,0));
    while(!q.empty()){
        node temp=q.top();
        q.pop();
        if(visited[temp.n]) continue;
        visited[temp.n]=true;
        for(int i=0;i<a[temp.n].size();i++){
            rule node1=a[temp.n][i];
            if(visited[node1.v]) continue;
            if(dis[node1.v]>node1.cost+temp.dis){
                dis[node1.v]=node1.cost+temp.dis;
                q.push(node(node1.v,dis[node1.v]));
            }
        }
    }
}
int main()
{
    cin>>n>>m>>k;
    init();
    for(int i=0;i<m;i++){
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        a[x].push_back(rule(x,y,z));
    }
    dij(k);
    for(int i=1;i<=n;i++) sum[i]+=dis[i];
    for(int i=1;i<=n;i++){
        dij(i);
        sum[i]+=dis[k];
    }
    int imax=0;
    for(int i=1;i<=n;i++){
        imax=max(imax,sum[i]);
    }
    cout<<imax<<endl;
    return 0;
}

3月25日:
4.poj 1511 Invitation Cards(优先队列+dij+链向式前向星存图)
其实这个题应该是昨天刷完的,跟上面的题可以说是一模一样,只是数据量太大了,当然,我继续用了上一题的方法,发现超时,以为是vector的原因,换了链向式前向星存图,发现还是超时,然后就继续优化读入函数等一切可以降低复杂度的操作,发现仍然超时(心态崩了,不写了)于是查了一下题解,竟然还有反向加边这种操作,心态炸裂:
因为本人并不喜欢函数传参这种操作,所以直接用了两个dij,复制粘贴
题解:

#pragma GCC optimize(3,"Ofast","inline")
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define maxn  1000010
//#define true false
//#define false true
const int MaxN = 0x3f3f3f3f;
const int MinN = 0xc0c0c00c;
const double pi = acos(-1);
typedef long long ll;
const int mod = 1e9 + 7;
using namespace std;
struct rule{
    int v,cost,next;
}edge[maxn],edge1[maxn];
int dis[maxn];
bool visited[maxn];
int n,m,k;
ll sum;
int head[maxn];
int head1[maxn];
struct node{
    int n,dis;
    node(int a,int b){n=a,dis=b;}
    bool operator < (const node & a)const
    {return dis>a.dis;}
};
int cnt=0,cnt1;
inline void add(int u,int v,int w){
    edge[cnt].cost=w;
    edge[cnt].v=v;
    edge[cnt].next=head[u];
    head[u]=cnt++;
}
inline void add1(int u,int v,int w){
    edge1[cnt1].cost=w;
    edge1[cnt1].v=v;
    edge1[cnt1].next=head1[u];
    head1[u]=cnt1++;
}
inline void dij(int x){
    memset(visited,false,sizeof(visited));
    memset(dis,MaxN,sizeof(dis));
    dis[x]=0;
    priority_queue<node> q;
    q.push(node(x,0));
    while(!q.empty()){
        node temp=q.top();
        q.pop();
        if(visited[temp.n]) continue;
        visited[temp.n]=true;
        for(int i=head[temp.n];i!=-1;i=edge[i].next){
            int v=edge[i].v;
            if(visited[v]) continue;
            if(dis[v]>temp.dis+edge[i].cost){
                dis[v]=temp.dis+edge[i].cost;
                q.push(node(v,dis[v]));

            }
        }
    }
}
inline void dij1(int x){
    memset(visited,false,sizeof(visited));
    memset(dis,MaxN,sizeof(dis));
    dis[x]=0;
    priority_queue<node> q;
    q.push(node(x,0));
    while(!q.empty()){
        node temp=q.top();
        q.pop();
        if(visited[temp.n]) continue;
        visited[temp.n]=true;
        for(int i=head1[temp.n];i!=-1;i=edge1[i].next){
            int v=edge1[i].v;
            if(visited[v]) continue;
            if(dis[v]>temp.dis+edge1[i].cost){
                dis[v]=temp.dis+edge1[i].cost;
                q.push(node(v,dis[v]));

            }
        }
    }
}

inline void init(){
    memset(head,-1,sizeof(head));
    memset(head1,-1,sizeof(head1));
    memset(visited,false,sizeof(visited));
    memset(dis,MaxN,sizeof(dis));
    sum=0;
    cnt=0;
    cnt1=0;
}
inline int read(){
   int s=0,w=1;
   char ch=getchar();
   while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
   while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
   return s*w;
}
int main()
{
    int t;
    cin>>t;
    while(t--){
        scanf("%d%d",&n,&m);
        init();
        for(int i=0;i<m;i++){
            int x,y,z;
            x=read(),y=read(),z=read();
            add(x,y,z);
            add1(y,x,z);
        }
//        for(int i=0;i
        dij(1);
  //      cout<
        for(int i=1;i<=n;i++) sum+=dis[i];
        dij1(1);
        for(int i=1;i<=n;i++) sum+=dis[i];
        printf("%lld\n",sum);
    }
    return 0;
}

5.Heavy Transportation POJ - 1797
题意:从1点到n点运送货物,每个每两个地方用桥梁链接,每个桥梁都有自己的最大承重,问:最大能运送多重的货物到达目的地。
注意是个无向图,注意每个例子之间多输出一行空行
这个题也是一个并不难的图论题,只不过就是把条件这里一块改了一下,当然,我是不会告诉你我这个题在条件这一块地方wa了好多次。

#pragma GCC optimize(3,"Ofast","inline")
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define maxn  1010
//#define true false
//#define false true
const int MaxN = 0x3f3f3f3f;
const int MinN = 0xc0c0c00c;
const double pi = acos(-1);
typedef long long ll;
const int mod = 1e9 + 7;
using namespace std;
struct wazxy{
    int to,val;
    wazxy(int a,int b){to=a,val=b;}
};
vector<vector<wazxy> > a;
struct node{
    int id,dis;
    node(int a,int b){id=a,dis=b;}
    bool operator < (const node & a)const
    {return dis<a.dis;}
};
bool visited[maxn];
int dis[maxn];
void init(){
    memset(visited,false,sizeof(visited));
    for(int i=0;i<=maxn;i++) dis[i]=0;
    a.resize(maxn);
    a.clear();
}
int n,m;
void dij(){
    dis[1]=MaxN;
    priority_queue<node> q;
    q.push(node(1,MaxN));
    while(!q.empty()){
        node temp=q.top();
        q.pop();
        if(visited[temp.id]) continue;
        visited[temp.id]=true;
        for(int i=0;i<a[temp.id].size();i++){
            int to=a[temp.id][i].to;
            if(visited[to]) continue;
            if(dis[to]<min(temp.dis,a[temp.id][i].val)){
                dis[to]=min(temp.dis,a[temp.id][i].val);
                q.push(node(to,dis[to]));
            }
        }
    }
}

int main()
{
    int t;
    cin>>t;
    int ans=1;
    while(t--){
        init();
        cin>>n>>m;
        for(int i=0;i<m;i++){
            int x,y,z;
            scanf("%d%d%d",&x,&y,&z);
            a[x].push_back(wazxy(y,z));
            a[y].push_back(wazxy(x,z));
        }
        dij();
        printf("Scenario #%d:\n",ans++);
        printf("%d\n",dis[n]);
        printf("\n");
    }
    return 0;
}

6.poj2253(dij变形+优先队列)
题意:就是找出从一个点到另一个点的所有道路,每条道路里都有都有最长的边,然后再从所有最长的边中找出最短的来输出。哦是不是很绕,反正我晕了一会。
跟头顶上的题目十分相似。

#pragma GCC optimize(3,"Ofast","inline")
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define maxn  1010
//#define true false
//#define false true
const int MaxN = 0x3f3f3f3f;
const int MinN = 0xc0c0c00c;
const double pi = acos(-1);
typedef long long ll;
const int mod = 1e9 + 7;
using namespace std;
struct wazxy{
    double to,val;
    wazxy(double a,double b){to=a,val=b;}
};
vector<vector<wazxy> > a;
struct node{
    int id;
    double dis;
    node(int a,double b){id=a,dis=b;}
    bool operator < (const node & a)const
    {return dis>a.dis;}
};
bool visited[maxn];
double dis[maxn];
void init(){
    memset(visited,false,sizeof(visited));
    for(int i=0;i<maxn;i++) dis[i]=MaxN;
    a.resize(maxn);
    a.clear();
}
int n;
void dij(){
    dis[1]=MaxN;
    priority_queue<node> q;
    q.push(node(1,0));
    while(!q.empty()){
        node temp=q.top();
        q.pop();
        double d=temp.dis;
        int u=temp.id;
        if(visited[u]) continue;
        for(int i=0;i<a[u].size();i++){
            wazxy node1=a[u][i];
            int v=node1.to;
            double w=node1.val;
            if(visited[v]) continue;
            if(dis[v]>max(w,d)){
                dis[v]=max(w,d);
               // cout<
                q.push(node(v,dis[v]));
            }
        }
    }
}
struct name{
    int x,y;
}s[210];
inline double getlen(double x,double y,double x1,double y1){
    return sqrt((x-x1)*(x-x1)+(y-y1)*(y-y1));
}

int main()
{
    int cnt=0;
    while(cin>>n&&n){
        init();
        cnt++;
        for(int i=1;i<=n;i++){
            cin>>s[i].x>>s[i].y;
        }
        for(int i=1;i<=n;i++){
            for(int f=i+1;f<=n;f++){
                double temp=getlen(s[i].x,s[i].y,s[f].x,s[f].y);
                a[i].push_back(wazxy(f,temp));
                a[f].push_back(wazxy(i,temp));
            }
        }
        dij();
        printf("Scenario #%d\n",cnt);
        printf("Frog Distance = %.3f\n\n",dis[2]);
        //for(int i=1;i<=n;i++) cout<
    }
    return 0;
}

7.hdu4725The Shortest Path in Nya Graph(建图建图建图+dij+优先队列优化)
搬运一下别人的翻译:n个点,m条边,以及相邻层之间移动的代价c,给出每个点所在的层数,以及m条边,每条边有u,v,c,表示从节点u到v(无向),并且移动的代价 c ,问说从 1 到 n 的代价最小是多少。
mdmdmd建图看别人的建图看了半小时才看懂,然后就是套模板了
其实就是把图层也看成点,对应的编号分别为n+1到n+n

#pragma GCC optimize(3,"Ofast","inline")
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define maxn  1000010
//#define true false
//#define false true
const int MaxN = 0x3f3f3f3f;
const int MinN = 0xc0c0c00c;
const double pi = acos(-1);
typedef long long ll;
const int mod = 1e9 + 7;
using namespace std;
int head[maxn];
struct wazxy{
    int v,w,next;
}edge[maxn];
bool visited[maxn];
bool vis[maxn];
int dis[maxn];
int f[maxn];
int n,m,c;
int cnt;
void init(){
    cnt=0;
    memset(visited,false,sizeof(visited));
    memset(vis,false,sizeof(vis));
    memset(head,-1,sizeof(head));
    memset(dis,MaxN,sizeof(dis));
}
void add(int u,int v,int w){
    edge[cnt].w=w;
    edge[cnt].v=v;
    edge[cnt].next=head[u];
    head[u]=cnt++;
}
struct node{
    int n,dis;
    node(int a,int b){n=a,dis=b;}
    bool operator < (const node & a)const
    {return dis>a.dis;}
};
inline void dij(){
    dis[1]=0;
    priority_queue<node> q;
    q.push(node(1,0));
    while(!q.empty()){
        node temp=q.top();
        q.pop();
        if(visited[temp.n]) continue;
        visited[temp.n]=true;
        for(int i=head[temp.n];i!=-1;i=edge[i].next){
            int v=edge[i].v;
            if(visited[v]) continue;
            if(dis[v]>temp.dis+edge[i].w){
                dis[v]=temp.dis+edge[i].w;
                q.push(node(v,dis[v]));

            }
        }
    }
}

int main()
{
    int t;
    cin>>t;
    int ans=1;
    while(t--){
        init();
        scanf("%d%d%d",&n,&m,&c);
        for(int i=1;i<=n;i++){
            scanf("%d",&f[i]);
            vis[f[i]]=true;
        }
        for(int i=1;i<n;i++){
            if(vis[i]&&vis[i+1]){
                add(n+i,n+i+1,c);
                add(n+i+1,n+i,c);
            }
        }
        for(int i=1;i<=n;i++){
            add(n+f[i],i,0);
            if(f[i]>1) add(i,n+f[i]-1,c);
            if(f[i]<n) add(i,n+f[i]+1,c);
        }
        int x,y,z;
        for(int i=1;i<=m;i++){
            scanf("%d%d%d",&x,&y,&z);
            add(x,y,z);
            add(y,x,z);
        }
        dij();
        printf("Case #%d: ",ans++);
        if(dis[n]<MaxN) printf("%d\n",dis[n]);
        else printf("-1\n");
    }
    return 0;
}

你可能感兴趣的:(数据结构,图论,最短路)