题解 P2984 【[USACO10FEB]给巧克力Chocolate Giving】

交了九九八十一遍,最后终于过了!这道题唯一的难点就是开的数据规模,然后就是一个裸的spfa最短路,下面见我这81次(其实没这么多)交的代码

1. 具体思路就是:让一只奶牛跑到FJ那边,然后再跑回p_i那里。
细心的朋友都发现了,这样太慢!!!而且常量开这么大跑两遍确实非常勉强
于是就爆零了!


1. 具体思路就是:让一只奶牛跑到FJ那边,然后再跑回p_i那里。
细心的朋友都发现了,这样太慢!!!而且常量开这么大跑两遍确实非常勉强
于是就爆零了!
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<queue>
#include<algorithm>

using namespace std ;
const int inf = 0x7fffffff;
const int maxn = 30000001 ;//这里是不是太大了!!
int n,m,t,k,s,e;
int dis[maxn] , vis[maxn] , head[maxn] ;
struct dy{
    int x , y , z ,next;
}a[maxn];
void add(int x , int y , int z)//加边
{
    a[t].x = x ;
    a[t].y = y ;
    a[t].z = z ;
    a[t].next = head[x] ;
    head[x] = t ++ ;
}
void spfa(int s)
{
    queue<int>q ;
    for(int i = 1 ; i <= n ; i ++) dis[i] = inf ;
    memset(vis , false , sizeof(vis)) ;
    q.push(s) ;
    dis[s] = 0 ;
    while(!q.empty())
    {
        int u = q.front() ;
        q.pop() ;
        vis[u] = 0 ;
        for(int i = head[u] ; i != -1 ; i = a[i].next )
        {
            int v = a[i].y ;
            if(dis[v] > dis[u] + a[i].z)
            {
                dis[v] = dis[u] + a[i].z ;
                if(!vis[v])
                {
                    vis[v] = true ;
                    q.push(v) ;
                }
            }
        }
    }
}
int p ;
int main()
{
    cin >> n >> m >> p ;
    memset(head , -1 , sizeof(head)) ;
    while(m --)//建图
    {
        int x , y , z ;
        cin >> x >> y >> z ;
        add(x , y , z ) ;
        add(y , x , z) ;
    }
    while( p --)//两遍SPFA
    {
        cin >> s >> e ;
        spfa(s) ;
        int w = dis[1] ;//先跑到FJ那里
        spfa(1) ;
        cout << w + dis[e] <<"\n";//再跑回P_I
    }
 } 

2.发现问题就要解决问题:上面说到常数太大的问题,于是便改吧!略微的超过一点数据范围,但是本蒟蒻有忽视了一个常识性问题:这是一个无向图!数组是要开两倍多一点的!
50分! 


2.发现问题就要解决问题:上面说到常数太大的问题,于是便改吧!略微的超过一点数据范围,但是本蒟蒻有忽视了一个常识性问题:这是一个无向图!数组是要开两倍多一点的!
50分!
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<queue>
#include<algorithm>

using namespace std ;
const int inf = 0x7ffffff;
const int maxn = 50010 ;//更改在此处!
int n,m,t,k,s,e;
int dis[maxn] , vis[maxn] , head[maxn] ;//注意这里!应优化为maxn*2+1
struct dy{
    int x , y , z ,next;
}a[maxn];
void add(int x , int y , int z)//加边
{
    a[t].x = x ;
    a[t].y = y ;
    a[t].z = z ;
    a[t].next = head[x] ;
    head[x] = t ++ ;
}
void spfa(int s)
{
    queue<int>q ;
    for(int i = 1 ; i <= n ; i ++) dis[i] = inf ;
    memset(vis , false , sizeof(vis)) ;
    q.push(s) ;
    dis[s] = 0 ;
    while(!q.empty())
    {
        int u = q.front() ;
        q.pop() ;
        vis[u] = 0 ;
        for(int i = head[u] ; i != -1 ; i = a[i].next )
        {
            int v = a[i].y ;
            if(dis[v] > dis[u] + a[i].z)
            {
                dis[v] = dis[u] + a[i].z ;
                if(!vis[v])
                {
                    vis[v] = true ;
                    q.push(v) ;
                }
            }
        }
    }
}
int p ;
int main()
{
    cin >> n >> m >> p ;
    memset(head , -1 , sizeof(head)) ;
    while(m --)
    {
        int x , y , z ;
        cin >> x >> y >> z ;
        add(x , y , z ) ;
        add(y , x , z) ;
    }
    while( p --)//打死不改的两遍spfa
    {
        cin >> s >> e ;
        spfa(s) ;
        int w = dis[1] ;
        spfa(1) ;
        cout << w + dis[e] <<"\n";
    }
 } 

3.改进:const 开大了一点,且maxn*2+1了,但是还是RE了一个点(而且吸氧还没用呢!)加上改进了算法:从奶牛到FJ的距离其实就和从FJ到奶牛的距离相等
所以只要求FJ到P_I和Q_I的距离之和就好了!! 


3.改进:const 开大了一点,且maxn*2+1了,但是还是RE了一个点(而且吸氧还没用呢!)加上改进了算法:从奶牛到FJ的距离其实就和从FJ到奶牛的距离相等
所以只要求FJ到P_I和Q_I的距离之和就好了!!
90分!
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<queue>
#include<algorithm>

using namespace std ;
const int inf = 0x7ffffff;
const int maxn = 60010 ;
int n,m,t,k,s,e;
int dis[maxn*2+1] , vis[maxn*2+1] , head[maxn*2+1] ;
struct dy{
    int x , y , z ,next;
}a[maxn*2+1];
void add(int x , int y , int z)
{
    a[t].x = x ;
    a[t].y = y ;
    a[t].z = z ;
    a[t].next = head[x] ;
    head[x] = t ++ ;
}
void spfa(int s)
{
    queue<int>q ;
    for(int i = 1 ; i <= n ; i ++) dis[i] = inf ;
    memset(vis , false , sizeof(vis)) ;
    q.push(s) ;
    dis[s] = 0 ;
    while(!q.empty())
    {
        int u = q.front() ;
        q.pop() ;
        vis[u] = 0 ;
        for(int i = head[u] ; i != -1 ; i = a[i].next )
        {
            int v = a[i].y ;
            if(dis[v] > dis[u] + a[i].z)
            {
                dis[v] = dis[u] + a[i].z ;
                if(!vis[v])
                {
                    vis[v] = true ;
                    q.push(v) ;
                }
            }
        }
    }
}
int p ;
int main()
{
    cin >> n >> m >> p ;
    memset(head , -1 , sizeof(head)) ;
    while(m --)
    {
        int x , y , z ;
        cin >> x >> y >> z ;
        add(x , y , z ) ;
        add(y , x , z) ;
    } 
    spfa(1) ;
    while( p --)//改为一遍spfa
    {
        cin >> s >> e ;
        cout <<dis[s] + dis[e] <<"\n";
    }
 } 

4.AC!
这么久了终于过了吗!long long 吗?我感觉和这个没什么大关系;我个人认为是我又把常数扩大了10倍的 


4.AC!
这么久了终于过了吗!long long 吗?我感觉和这个没什么大关系;我个人认为是我又把常数扩大了10倍的原因;
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<queue>
#include<algorithm>

using namespace std ;
#define ll long long 
const ll inf = 0x7ffffff;
const ll maxn = 1000010 ;//这里扩大了10倍
ll n,m,t,k,s,e;
ll dis[maxn] , vis[maxn] , head[maxn] ;
struct dy{
    ll x , y , z ,next;
}a[maxn];
void add(ll x , ll y , ll z)
{
    a[t].x = x ;
    a[t].y = y ;
    a[t].z = z ;
    a[t].next = head[x] ;
    head[x] = t ++ ;
}
void spfa(ll s)
{
    queue<ll>q ;
    for(ll i = 1 ; i <= n ; i ++) dis[i] = inf ;
    memset(vis , false , sizeof(vis)) ;
    q.push(s) ;
    dis[s] = 0 ;
    while(!q.empty())
    {
        ll u = q.front() ;
        q.pop() ;
        vis[u] = 0 ;
        for(ll i = head[u] ; i != -1 ; i = a[i].next )
        {
            ll v = a[i].y ;
            if(dis[v] > dis[u] + a[i].z)
            {
                dis[v] = dis[u] + a[i].z ;
                if(!vis[v])
                {
                    vis[v] = true ;
                    q.push(v) ;
                }
            }
        }
    }
}
int p ;
int main()
{
    cin >> n >> m >> p ;
    memset(head , -1 , sizeof(head)) ;
    while(m --)
    {
        ll x , y , z ;
        cin >> x >> y >> z ;
        add(x , y , z ) ;
        add(y , x , z) ;
    } 
    spfa(1) ;
    while( p --)//改为一遍spfa
    {
        cin >> s >> e ;
        cout <<dis[s] + dis[e] <<"\n";
    }
 } 

完结散花!!