[CCF CSP]201712-4 行车路线

暴力+剪枝 只得了40分...暂时没想到正解(好吧,查了一下正解dijkstra

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll N=500+10;
const ll INF=0x3f3f3f3f;
ll n,m;
struct edge{
    ll type;
    ll to;
    ll w;
    edge(){}
    edge(ll t,ll b,ll c){type=t;to=b;w=c;}
};
vector<edge> g[N];
ll vis[N],d[N];
ll t,a,b,c,ans;
void dfs(ll u,ll pre,ll flag,ll sum,ll x)//x为已走小道长度
{
    if(sum>ans) return;
    if(sum>=d[u]) return;
    if(u==n)
    {
        ans=min(sum,ans);
        return;
    }
    for(ll i=0;i<g[u].size();i++)
    {
        ll v=g[u][i].to,w=g[u][i].w;
        if(v==pre) continue;
        if(vis[v]) continue;
        vis[v]=1;
        ll f=g[u][i].type,t_sum,xx;
        if(f==0)
        {
            t_sum=sum+w;
            xx=0;
        }
        else {
            t_sum=sum-x*x;
            xx=x+w;
            t_sum+=xx*xx;
        }
        dfs(v,u,f,t_sum,xx);
        vis[v]=0;
    }
    d[u]=min(d[u],sum);
}
int main()
{
    //ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    scanf("%lld%lld",&n,&m);
    for(ll i=0;i<m;i++)
    {
        scanf("%lld%lld%lld%lld",&t,&a,&b,&c);
        g[a].push_back(edge(t,b,c));
        g[b].push_back(edge(t,a,c));
    }
    ans=INF;
    memset(vis,0,sizeof(vis));
    memset(d,INF,sizeof(d));
    vis[1]=1;
    dfs(1,-1,0,0,0);
    printf("%lld
",ans);
    return 0;
}
/*
6 7
1 1 2 3
1 2 3 2
0 1 3 30
0 3 4 20
0 4 5 30
1 3 5 6
1 5 6 1
*/

 下面是100分代码,虽然题中说答案不超过1e6,但是不保证其他点到点1的距离不爆int。。还是都改为longlong吧,不然只有80分

思路就是在dijkstra算法,维护未选中点到源点距离时,判断一下边的类型,并且队列中每个点记录其是通过哪种类型的边过来的以及如果是小道,已走过的长度是多少。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pb(x) push_back(x)
const ll N=510;
const ll INF=0x3f3f3f3f;
ll n,m;
struct Edge{
    ll k;
    ll to;
    ll w;
    Edge(){}
    Edge(ll a,ll b,ll c){k=a;to=b;w=c;}
};
struct Node{
    ll num;
    ll dis;
    ll f;
    ll x;
    Node(){}
    Node(ll a,ll b,ll c,ll d){num=a;dis=b;f=c;x=d;}
};
vector<Edge> g[N];
priority_queue<Node> que;
bool operator<(const Node&a,const Node&b){
    return a.dis>b.dis;
}
ll dis[N],vis[N];
void dijkstra()
{
    memset(dis,INF,sizeof(dis));
    memset(vis,0,sizeof(vis));
    while(!que.empty()) que.pop();
    dis[1]=0;
    que.push(Node(1,0,0,0));
    while(!que.empty())
    {
        Node now=que.top();
        que.pop();
        ll u=now.num,f=now.f,x=now.x;
        if(vis[u]) continue;
        //cout<<"arrive"<<u<<endl;
        vis[u]=1;
        if(u==n) return;
        for(ll i=0;i<g[u].size();i++)
        {
            ll v=g[u][i].to;
            if(vis[v]) continue;
            ll temp,w=g[u][i].w,k=g[u][i].k;
            if(k==0)
            {
                temp=dis[u]+w;
                if(temp<dis[v]){
                    dis[v]=temp;
                    que.push(Node(v,temp,0,0));
                }
            }
            else if(k==1)
            {
                if(f==1) {
                    temp=dis[u]-x*x+(x+w)*(x+w);
                    if(temp<dis[v]){
                        dis[v]=temp;
                        que.push(Node(v,temp,1,x+w));
                    }
                }
                else{
                    temp=dis[u]+w*w;
                    if(temp<dis[v]){
                        dis[v]=temp;
                        que.push(Node(v,temp,1,w));
                    }
                }
            }
            //cout<<" update"<<v<<" "<<dis[v]<<endl;
        }
    }
}
int main()
{
    scanf("%lld%lld",&n,&m);
    ll t,a,b,c;
    for(ll i=0;i<m;i++)
    {
        scanf("%lld%lld%lld%lld",&t,&a,&b,&c);
        g[a].pb(Edge(t,b,c));
        g[b].pb(Edge(t,a,c));
    }
    dijkstra();
    printf("%lld
",dis[n]);
    return 0;
}
原文地址:https://www.cnblogs.com/Andrew-aq/p/12500735.html