现在的位置: 首页 > 综合 > 正文

BZOJ 1975 魔法猪学院(K短路)

2013年12月17日 ⁄ 综合 ⁄ 共 3571字 ⁄ 字号 评论关闭

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1975

题意:给出一个带权有向图。求一个最大的K使得前K短路的长度之和不大于给定的值Sum。


思路:首先,求出每个点到n的最短路。接着,使用优先队列,节点为(D,u)。首先将(dis[1],1)进队。由于D在任意时候为一条1到n的路径的长度,那么对于边<u,v,w>,D-dis[u]+w+dis[v]为一条新的路径的长度。


#include <iostream>
#include <cstdio>
#include <string.h>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <map>
#include <ctype.h>
#include <time.h>
   
   
#define abs(x) ((x)>=0?(x):-(x))
#define i64 long long
#define u32 unsigned int
#define u64 unsigned long long
#define clr(x,y) memset(x,y,sizeof(x))
#define CLR(x) x.clear()
#define ph(x) push(x)
#define pb(x) push_back(x)
#define Len(x) x.length()
#define SZ(x) x.size()
#define PI acos(-1.0)
#define sqr(x) ((x)*(x))
#define MP(x,y) make_pair(x,y)
#define EPS 1e-7
   
   
#define FOR0(i,x) for(i=0;i<x;i++)
#define FOR1(i,x) for(i=1;i<=x;i++)
#define FOR(i,a,b) for(i=a;i<=b;i++)
#define FORL0(i,a) for(i=a;i>=0;i--)
#define FORL1(i,a) for(i=a;i>=1;i--)
#define FORL(i,a,b)for(i=a;i>=b;i--)
   
   
#define rush() int CC;for(scanf("%d",&CC);CC--;)
#define Rush(n)  while(scanf("%d",&n)!=-1)
using namespace std;
   
   
void RD(int &x){scanf("%d",&x);}
void RD(i64 &x){scanf("%lld",&x);}
void RD(u64 &x){scanf("%I64u",&x);}
void RD(u32 &x){scanf("%u",&x);}
void RD(double &x){scanf("%lf",&x);}
void RD(int &x,int &y){scanf("%d%d",&x,&y);}
void RD(i64 &x,i64 &y){scanf("%lld%lld",&x,&y);}
void RD(u32 &x,u32 &y){scanf("%u%u",&x,&y);}
void RD(double &x,double &y){scanf("%lf%lf",&x,&y);}
void RD(double &x,double &y,double &z){scanf("%lf%lf%lf",&x,&y,&z);}
void RD(int &x,int &y,int &z){scanf("%d%d%d",&x,&y,&z);}
void RD(i64 &x,i64 &y,i64 &z){scanf("%lld%lld%lld",&x,&y,&z);}
void RD(u32 &x,u32 &y,u32 &z){scanf("%u%u%u",&x,&y,&z);}
void RD(char &x){x=getchar();}
void RD(char *s){scanf("%s",s);}
void RD(string &s){cin>>s;}
   
   
void PR(int x) {printf("%d\n",x);}
void PR(int x,int y) {printf("%d %d\n",x,y);}
void PR(i64 x) {printf("%I64d\n",x);}
void PR(i64 x,i64 y) {printf("%lld %lld\n",x,y);}
void PR(u32 x) {printf("%u\n",x);}
void PR(u64 x) {printf("%llu\n",x);}
void PR(double x) {printf("%.10lf\n",x);}
void PR(double x,double y) {printf("%.6lf %.5lf\n",x,y);}
void PR(char x) {printf("%c\n",x);}
void PR(char *x) {printf("%s\n",x);}
void PR(string x) {cout<<x<<endl;}

void upMin(int &x,int y) {if(x>y) x=y;}
void upMin(i64 &x,i64 y) {if(x>y) x=y;}
void upMin(double &x,double y) {if(x>y) x=y;}
void upMax(int &x,int y) {if(x<y) x=y;}
void upMax(i64 &x,i64 y) {if(x<y) x=y;}
void upMax(double &x,double y) {if(x<y) x=y;}
   
const int mod=1000000007;
const i64 inf=((i64)1)<<60;
const double dinf=10000000000.0;
const int INF=100000000;
const int N=50005;

vector<pair<int,double> > g[N],g1[N];
double dis[N];
int n,m;
double Sum;

struct node
{
    int v;
    double dis;
    
    node(){}
    node(int _v,double _dis)
    {
        v=_v;
        dis=_dis;
    }
    
    int operator<(const node &a) const
    {
        return dis>a.dis;
    }
};

int inq[N];

void SPFA()
{
    int i;
    FOR1(i,n) dis[i]=dinf;
    dis[n]=0; inq[n]=1;
    queue<int> Q;
    Q.push(n);
    int u,v;
    double w;
    while(!Q.empty())
    {
        u=Q.front();
        Q.pop();
        
        inq[u]=0;
        FOR0(i,SZ(g1[u]))
        {
            v=g1[u][i].first;
            w=g1[u][i].second;
            if(dis[v]>dis[u]+w)
            {
                dis[v]=dis[u]+w;
                if(!inq[v]) inq[v]=1,Q.push(v);
            }
        }
    }
}

priority_queue<node> Q;

int cal()
{
    Q.push(node(1,dis[1]));
    int ans=0,i,v;
    node p;
    double w;
    while(!Q.empty())
    {
        p=Q.top();
        Q.pop();
        
        if(p.dis>Sum+EPS) break;
        
        if(p.v==n) 
        {
            ans++;
            Sum-=p.dis;
            continue;
        }
        FOR0(i,SZ(g[p.v]))
        {
            v=g[p.v][i].first;
            w=g[p.v][i].second;
            Q.push(node(v,p.dis-dis[p.v]+w+dis[v]));
        }
    }
    return ans;
}

int main()
{
    RD(n,m); RD(Sum);
    int i,u,v;
    double w;
    FOR1(i,m)
    {
        RD(u,v);RD(w);
        g[u].pb(MP(v,w));
        g1[v].pb(MP(u,w));
    }
    SPFA();
    PR(cal());
}

抱歉!评论已关闭.