zoukankan      html  css  js  c++  java
  • Codeforces 1321D Navigation System

    题意

    有个人要从(s)走到(t),经过的路径给定。导航系统每次会显示当前节点到(t)的最短路,有多条就显示其中之一。这个人如果按照导航走,那么啥都没变。如果没有按导航走导航就会重新导航。问重新导航的最小和最大次数。

    解题思路

    建反图,在反图上以(t)为源跑dijkstra最短路。

    在原图上dfs

    • 若下一个节点到(t)的距离是所有邻接节点中最短的
      • 如果到(t)最短的节点只有一个,那么什么都不变。
      • 如果不止一个,那么最大次数加1。
    • 若下一个节点到(t)的距离不是所有邻接节点中最短的,那么最大次数和最小次数都加1。

    AC代码

    #include <bits/stdc++.h>
    using namespace std;
      
    typedef long long ll;
    typedef pair<int,int> pi;
      
    #define sz(x) ((int)(x).size())
    #define all(x) (x).begin(),(x).end()
    #define rall(x) (x).rbegin(),(x).rend()
    #define endl '
    '
      
    const double PI=acos(-1.0);
      
    namespace IO{
        bool REOF = 1;//为0表示文件结尾
        inline char nc() {
            static char buf[100000], *p1 = buf, *p2 = buf;
            return p1 == p2 && REOF && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2) ? (REOF = 0, EOF) : *p1++;
        }
      
        template<class T>
        inline bool read(T &x) {
            if(!REOF)return false;
            char c = nc();bool f = 0; x = 0;
            while (c<'0' || c>'9')c == '-' && (f = 1), c = nc();
            while (c >= '0'&&c <= '9')x = (x << 3) + (x << 1) + (c ^ 48), c = nc();
            if(f)x=-x;
            return true;
        }
      
        template<typename T, typename... T2>
        inline bool read(T &x, T2 &... rest) {
            if(!REOF)return false;
            read(x);
            return read(rest...);
        }
      
      
        inline bool need(char &c) { return ((c >= 'a') && (c <= 'z')) || ((c >= '0') && (c <= '9')) || ((c >= 'A') && (c <= 'Z')); }
        // inline bool need(char &c) { return ((c >= 'a') && (c <= 'z')) || ((c >= '0') && (c <= '9')) || ((c >= 'A') && (c <= 'Z')) || c==' '; }
      
        inline bool read_str(char *a) {
            if(!REOF)return false;
            while ((*a = nc()) && need(*a) && REOF)++a; *a = '';
            return true;
        }
      
        inline bool read_dbl(double &x){
            if(!REOF)return false;
            bool f = 0; char ch = nc(); x = 0;
            while(ch<'0'||ch>'9')  {f|=(ch=='-');ch=nc();}
            while(ch>='0'&&ch<='9'){x=x*10.0+(ch^48);ch=nc();}
            if(ch == '.') {
                double tmp = 1; ch = nc();
                while(ch>='0'&&ch<='9'){tmp=tmp/10.0;x=x+tmp*(ch^48);ch=nc();}
            }
            if(f)x=-x;
            return true;
        }
      
        template<class TH> void _dbg(const char *sdbg, TH h){ cerr<<sdbg<<'='<<h<<endl; }
      
        template<class TH, class... TA> void _dbg(const char *sdbg, TH h, TA... a) {
            while(*sdbg!=',')cerr<<*sdbg++;
            cerr<<'='<<h<<','<<' '; _dbg(sdbg+1, a...);
        }
         
        template<class T> ostream &operator<<(ostream& os, vector<T> V) {
            os << "["; for (auto vv : V) os << vv << ","; return os << "]";
        }
      
        template<class L, class R> ostream &operator<<(ostream &os, pair<L,R> P) {
            return os << "(" << P.st << "," << P.nd << ")";
        }
         
        #define debug(...) _dbg(#__VA_ARGS__, __VA_ARGS__)
    }
      
    using namespace IO;
    const int maxn=2e5+5;
    const int maxv=2e5+5;
    const int mod=998244353; // 998244353 1e9+7
    const int INF=1e9+7; // 1e9+7 0x3f3f3f3f 0x3f3f3f3f3f3f3f3f
    const double eps=1e-12;
      
    int dx[4]={0,1,0,-1};
    //int dx[8]={1,0,-1,1,-1,1,0,-1};
    int dy[4]={1,0,-1,0};
    //int dy[8]={1,1,1,0,0,-1,-1,-1};
     
    // #define ls (x<<1)
    // #define rs (x<<1|1)
    // #define mid ((l+r)>>1)
    // #define lson ls,l,mid
    // #define rson rs,mid+1,r
     
      
    /**
     * **********     Backlight     **********
     * 仔细读题
     * 注意边界条件
     * 记得注释输入流重定向
     * 没有思路就试试逆向思维
     * 加油,奥利给
     */
     
    struct Graph{
    	int tot,head[maxn];
    	struct Edge{
    		int v,nxt;
    	}e[maxn<<1];
    	void init(){
    		tot=1;
    		memset(head,0,sizeof(head));
    	}
    	void addedge(int u,int v){
    		e[tot].v=v;e[tot].nxt=head[u];
    		head[u]=tot++;
    		
    		// e[tot].v=u;e[tot].nxt=head[v];
    		// head[v]=tot++;
    	}
    }G1,G2;
     
    int n,m,k,p[maxn],dis[maxn];
    int mi,ma;
    void dijkstra(int S){
    	priority_queue<pi, vector<pi>, greater<pi> > q;
    	for (int i = 1; i <= n; i++) dis[i] = INF;
    	dis[S] = 0; q.push(make_pair(0, S));
    	while (!q.empty()){
    		pi p = q.top(); q.pop();
    		if (dis[p.second] != p.first) continue;
    		for (int i = G2.head[p.second]; i; i=G2.e[i].nxt){
    			int v = G2.e[i].v, w=1;
    			if (dis[v] > dis[p.second] + w){
    				dis[v] = dis[p.second] + w;
    				q.push(make_pair(dis[v], v));
    			}
    		}
    	}
    }
     
    void dfs(int id){
    	if(id==k){
     
    		return;
    	}
    	int u=p[id],w=p[id+1];
    	int MIN=INF,cnt=0;
    	for(int i=G1.head[u];i;i=G1.e[i].nxt){
    		int v=G1.e[i].v;
    		if(dis[v]<MIN){
    			MIN=dis[v];
    			cnt=0;
    		}
    		if(dis[v]==MIN)cnt++;
    	}
     
    	if(dis[w]==MIN){
    		if(cnt>1)ma++;
    	}
    	if(dis[w]>MIN){
    		mi++;
    		ma++;
    	}
    	dfs(id+1);
    }
     
    void solve(){
    	read(n,m);
    	int u,v;
    	G1.init(); G2.init();
    	for(int i=1;i<=m;i++){
    		read(u,v);
    		G1.addedge(u,v);
    		G2.addedge(v,u);
    	}
    	read(k);
    	for(int i=1;i<=k;i++)read(p[i]);
     
    	dijkstra(p[k]);
     
    	dfs(1);
    	printf("%d %d
    ",mi,ma);
    }
     
    int main()
    {
        // freopen("in.txt","r",stdin);
        // ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
        // int _T; read(_T); for(int _=1;_<=_T;_++)solve();
        // while(read(n))solve();
        solve();
        return 0;
    }
    
  • 相关阅读:
    Ajax基础知识详解
    php 基础语法整理
    06 js-递归
    原生js 实现瀑布流布局
    解决高度坍塌问题
    jQuery动画效果
    jQuery增删元素类名
    JQueryTab栏切换(important!)
    jQuery排他思想(important!)
    jQuery设置元素样式
  • 原文地址:https://www.cnblogs.com/zengzk/p/12404305.html
Copyright © 2011-2022 走看看