zoukankan      html  css  js  c++  java
  • 2019-2020 ICPC Southwestern European Regional Programming Contest (SWERC 2019-20)

    传送门

    A. Environment-Friendly Travel

    注意到(N*B)很小,所以我们利用这个作为状态跑(dp)就行。时间复杂度为(O(10^8))左右。
    比较套路的(dp)了。

    Code
    /*
     * Author:  heyuhhh
     * Created Time:  2020/5/21 16:59:22
     */
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    #include <cmath>
    #include <set>
    #include <map>
    #include <queue>
    #include <iomanip>
    #include <assert.h>
    #define MP make_pair
    #define fi first
    #define se second
    #define pb push_back
    #define sz(x) (int)(x).size()
    #define all(x) (x).begin(), (x).end()
    #define INF 0x3f3f3f3f
    #define Local
    #ifdef Local
      #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
      void err() { std::cout << std::endl; }
      template<typename T, typename...Args>
      void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
      template <template<typename...> class T, typename t, typename... A> 
      void err(const T <t> &arg, const A&... args) {
      for (auto &v : arg) std::cout << v << ' '; err(args...); }
    #else
      #define dbg(...)
    #endif
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    //head
    const int maxN = 1000 + 5, maxM = 105, MAX = 20005;
     
    int T, N, B;
    int c[maxN];
    int cost[maxN][maxN], w[maxN][maxN];
     
    struct Point {
        int x, y;
    }p[maxN];
     
    int distance(int i, int j) {
        return (int)ceil(hypot(p[i].x - p[j].x, p[i].y - p[j].y) - 1e-9);
    }
     
    int dis[maxN][maxM];
    struct Dijkstra{
        struct node{
            int val, d, u;
            bool operator < (const node &A) const {
                return val > A.val;
            }
        };
        bool vis[maxN][maxM];
        void dij(int s) {
            priority_queue <node> q;
            memset(dis, INF, sizeof(dis));
            memset(vis, 0, sizeof(vis));
            dis[s][0] = 0;
            q.push(node{0, 0, 0});
            while(!q.empty()) {
                node cur = q.top(); q.pop();
                int u = cur.u, d = cur.d;
                if(vis[u][d]) continue;
                vis[u][d] = 1;
                for (int v = 0; v <= N + 1; v++) {
                    int dist = w[u][v];
                    if (d + dist > B) continue;
                    if(dis[v][d + dist] > dis[u][d] + cost[u][v]) {
                        dis[v][d + dist] = dis[u][d] + cost[u][v];
                        q.push(node{dis[v][d + dist], d + dist, v});
                    }
                }   
            }
        }
    }solver;
     
    void run() {
        cin >> p[0].x >> p[0].y;
        int ex, ey; cin >> ex >> ey;
        cin >> B >> c[0] >> T;
        for (int i = 1; i <= T; i++) {
            cin >> c[i];
        }
        cin >> N;
        vector <pair<int, pii>> edges;
        for (int i = 1; i <= N; i++) {
            cin >> p[i].x >> p[i].y;
            int k; cin >> k;
            while (k--) {
                int j, t; cin >> j >> t; ++j;
                edges.push_back(MP(i, MP(j, t)));
            }
        }
        p[N + 1] = Point{ex, ey};
        for (int i = 0; i <= N + 1; i++) {
            for (int j = 0; j <= N + 1; j++) {
                w[i][j] = distance(i, j);
            }
        }
        memset(cost, INF, sizeof(cost));
        for (int i = 1; i <= N; i++) {
            cost[0][i] = c[0] * w[0][i];
            cost[i][N + 1] = c[0] * w[i][N + 1];
        }
        cost[0][N + 1] = c[0] * w[0][N + 1];
        for (auto it : edges) {
            int i = it.fi;
            int j = it.se.fi, t = it.se.se;   
            cost[i][j] = cost[j][i] = min(cost[i][j], c[t] * w[i][j]);
        }
        solver.dij(0);
        int ans = INF;
        for (int i = 0; i <= B; i++) {
            ans = min(ans, dis[N + 1][i]);
        }
        if (ans == INF) ans = -1;
        cout << ans << '
    ';
    }
     
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cout << fixed << setprecision(20);
        run();
        return 0;
    }
    

    B. Biodiversity

    签到。

    Code
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    typedef double db;
    typedef long double ld;
    const int MAXN = 1e6 + 5, MAXM = 4e5 + 5, BOUND = 2e5, MOD = 998244353, INF = 0x3f3f3f3f, base = 10000;
    const int inv2 = (MOD + 1) >> 1;
    const ll INFL = 0x3f3f3f3f3f3f3f3f;
    const double PI = acos(-1.0), eps = 1e-9;
    #define lson o<<1,l,m
    #define rson o<<1|1,m+1,r
    #define lc(x) ch[x][0]
    #define pii pair<int,int>
    #define vi vector<int>
    #define vii vector<pair<int,int>>
    #define rc(x) ch[x][1]
    #define random(a,b) ((a)+rand()%((b)-(a)+1))
    #define all(a) (a).begin(), (a).end()
    #define sz(a) int(a.size())
    #define rep(i,a,b) for(int i=(a);i<=(b);i++)
    #define fi first
    #define se second
    #define MP std::make_pair
    #define ri register int
    //#define sz(a) int((a).size())
    const int N = 2e5,M = (1<<20);
    inline int add(int a, int b) {return a + b >= MOD ? a + b - MOD : a + b;}
    inline int dec(int a, int b) {return a < b ? a - b + MOD : a - b;}
    inline int mul(int a, int b) {return 1ll * a * b % MOD;}
    template <typename T>
    inline void cmin(T &a,T b){a = min(a,b);}
    template <typename T>
    inline void cmax(T &a,T b){a = max(a,b);}
    ll qpow(ll a,ll b){
        ll ans=1;
        for(;b;b>>=1,a=a*a%MOD)if(b&1)ans=ans*a%MOD;
        return ans;
    }
    mt19937 mrand(random_device{}());
    map<string,int> mp;
    void run(){
        int n; cin>>n;
        string tmp;
        rep(i,1,n)cin>>tmp,mp[tmp]++;
        int mx=0;
        string ans;
        for(auto &e:mp){
            if(e.second > mx){
                mx = e.second;
                ans = e.first;
            }
        }
        if(mx > n-mx){
            cout<<ans<<'
    ';
        }else cout<<"NONE
    ";
    }
    int main() {
        ios::sync_with_stdio(false); cin.tie(0);
        int _=1;
        while(_--)run();
        return 0;
    }
    

    C. Ants

    直接枚举就行,很大的数没什么用。

    Code
    /*
     * Author:  heyuhhh
     * Created Time:  2020/5/21 13:45:08
     */
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    #include <cmath>
    #include <set>
    #include <map>
    #include <queue>
    #include <iomanip>
    #include <assert.h>
    #define MP make_pair
    #define fi first
    #define se second
    #define pb push_back
    #define sz(x) (int)(x).size()
    #define all(x) (x).begin(), (x).end()
    #define INF 0x3f3f3f3f
    #define Local
    #ifdef Local
      #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
      void err() { std::cout << std::endl; }
      template<typename T, typename...Args>
      void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
      template <template<typename...> class T, typename t, typename... A> 
      void err(const T <t> &arg, const A&... args) {
      for (auto &v : arg) std::cout << v << ' '; err(args...); }
    #else
      #define dbg(...)
    #endif
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    //head
    const int N = 1e6 + 5;
     
    void run() {
        int n; cin >> n;
        vector <int> a;
        for (int i = 1; i <= n; i++) {
            string s; cin >> s;
            int len = s.length();
            if (s[0] == '-' || len > 100) continue;
            if (len < 9) {
                int x = 0;
                for (int j = 0; j < len; j++) {
                    x = x * 10 + s[j] - '0';
                }
                a.push_back(x);
            }
        }
        sort(all(a));
        for (int i = 0, j = 0;; i++, j++) {
            if (j >= sz(a) || i != a[j]) {
                cout << i << '
    ';
                return;
            }
        }
    }
     
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cout << fixed << setprecision(20);
        run();
        return 0;
    }
    

    F. Icebergs

    模拟一下。

    Code
    #include<cstdio>
    #include<cmath>
    #define REP(i,a,b) for(int i=(a); i<(b); i++)
    #define REPE(i,a,b) for(int i=(a); i<=(b); i++)
    using namespace std;
    #define D Point
    #define CD const D
    struct D { double x,y;};
    double cross(CD&l, CD&r) {return l.x*r.y-l.y*r.x;}
    template<class T, int Z>
    struct Arr {
    	T data[Z]; int n;
    	Arr() :n(0) {}
    	T&operator[](int z) {return data[z];}
    	void push(const T&x) {data[n++]=x;}
    	void pop() {n--;}
    };
    typedef Arr<D,57> Plg;
    /*void tubao(Plg &p, Plg &ch) {
    	sort(p.data,p.data+p.n);
    	int &m=ch.n; m=0;
    	REP(i,0,p.n) {
    		while(m>1 && cross(ch[m-1]-ch[m-2], p[i]-ch[m-2])<=0 ) m--;
    		ch[m++]=p[i];
    	}
    	int k=m;
    	PERE(i,p.n-2,0) {
    		while(m>k && cross(ch[m-1]-ch[m-2], p[i]-ch[m-2])<=0) m--;
    		ch[m++]=p[i];
    	}
    	if(p.n>1) m--;
    }*/
    double area(Plg &p) {
    	double ans=0;
    	REP(i,0,p.n) {
    		ans+=cross(p[i], p[(i+1)%p.n]);;
    	}
    	return fabs(ans/2);
    }
    #undef D
    #undef CD
    Plg p;
    int main() {
    	int n; scanf("%d", &n);
    	double ans=0;
    	while(0<n--) {
    		
    		scanf("%d", &p.n);
    		for(int i=0; i<p.n; i++) {
    			scanf("%lf%lf", &p[i].x, &p[i].y);
    		}
    		ans+=area(p);
    	}
    	printf("%.0lf
    ", floor(ans));
    	return 0;
    }
    

    G. Swapping Places

    题意:
    给定(s,sleq 200)种物品,给定(l,lleq 10000)组关系,若关系中的两种物品相邻那么就可以交换。
    给定长度为(n)的序列,每个位置上面为一种物品,现在要求出字典序最小的最终序列。

    思路:
    我们可以思考一下贪心的做法:

    • 考虑依次确定(1,2,...,n)位置上面的数,确定位置(i)时,我们贪心将字典序最小的物品往前面移动,最终(i)位置上面的数即是最终答案。

    简单说一下贪心做法的正确性,我们每一轮优先移动字典序最小的,如果没能到达(i),那么当前物种必然不可能位于位置(i)
    但以上的思想可能复杂度不对or码量较大。
    因为我们目前的做法是从后往前,我们可以考虑从前往后,为每种物品给定一个最优位置。那么我们还是按字典序最小的来,我们每次将最优匹配指针往后移动直至不能移动,若当前指针指向的位置为当前物品,那么此时等价于将其往前面移动能够成功到(i),所以就确定了答案。

    从后往前的话可能会对每一种物品涉及到多个指针,每次取出第一个指针往前移动。但我们可以让这些指针保持不变,用一个指针从前往后移动,这样码量上会好很多。
    很巧妙的做法。

    Code
    /*
     * Author:  heyuhhh
     * Created Time:  2020/5/22 10:52:27
     */
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    #include <cmath>
    #include <set>
    #include <map>
    #include <queue>
    #include <iomanip>
    #include <assert.h>
    #define MP make_pair
    #define fi first
    #define se second
    #define pb push_back
    #define sz(x) (int)(x).size()
    #define all(x) (x).begin(), (x).end()
    #define INF 0x3f3f3f3f
    #define Local
    #ifdef Local
      #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
      void err() { std::cout << std::endl; }
      template<typename T, typename...Args>
      void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
      template <template<typename...> class T, typename t, typename... A> 
      void err(const T <t> &arg, const A&... args) {
      for (auto &v : arg) std::cout << v << ' '; err(args...); }
    #else
      #define dbg(...)
    #endif
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    //head
    const int N = 1e5 + 5;
     
    void run() {
        int s, l, n;
        cin >> s >> l >> n;
        vector <string> str(s);
        for (int i = 0; i < s; i++) {
            cin >> str[i];
        }
        sort(all(str));
        map <string, int> mp;
        for (int i = 0; i < s; i++) {
            mp[str[i]] = i;
        }
        map <int, string> mp2;
        for (int i = 0; i < s; i++) {
            mp2[i] = str[i];
        }
        vector <vector <int>> w(s, vector <int> (s));
        for (int i = 0; i < l; i++) {
            string ss, tt; cin >> ss >> tt;
            w[mp[ss]][mp[tt]] = w[mp[tt]][mp[ss]] = 1;
        }
        vector <int> a(n);
        for (int i = 0; i < n; i++) {
            string ss; cin >> ss;
            a[i] = mp[ss]; 
        }
        vector <int> cnt(s);
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < s; j++) {
                while (cnt[j] < n && (a[cnt[j]] == -1 || w[a[cnt[j]]][j])) {
                    ++cnt[j];
                }
                if (cnt[j] < n && a[cnt[j]] == j) {
                    a[cnt[j]] = -1;
                    cout << mp2[j] << ' ';
                    break;
                }
            }
        }
    }
     
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cout << fixed << setprecision(20);
        run();
        return 0;
    }
    

    还有一种不那么废脑子的做法,就是我们很容易发现不能交换的物种他们的相对顺序不会发生改变。
    我们根据这一点进行建图,若(i)位置的物种不能和(j)位置的物种交换((i<j)),那么连边(i ightarrow j)
    那么问题就等价于求出一种字典序最小的拓扑序。
    但对每个位置(j)这样直接连边的话空间会炸,可能会到(O(n^2))。这里连边其实可以优化:对于每个位置,往前面的物种至多连一条边即可,没必要多连,这样就可以保证拓扑序。
    细节见代码:

    Code
    /*
     * Author:  heyuhhh
     * Created Time:  2020/5/22 11:11:26
     */
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    #include <cmath>
    #include <set>
    #include <map>
    #include <queue>
    #include <iomanip>
    #include <assert.h>
    #define MP make_pair
    #define fi first
    #define se second
    #define pb push_back
    #define sz(x) (int)(x).size()
    #define all(x) (x).begin(), (x).end()
    #define INF 0x3f3f3f3f
    #define Local
    #ifdef Local
      #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
      void err() { std::cout << std::endl; }
      template<typename T, typename...Args>
      void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
      template <template<typename...> class T, typename t, typename... A> 
      void err(const T <t> &arg, const A&... args) {
      for (auto &v : arg) std::cout << v << ' '; err(args...); }
    #else
      #define dbg(...)
    #endif
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    //head
     
    struct node {
        int u, val;
        bool operator < (const node &A) const {
            return val > A.val;
        }   
    };
     
    void run() {
        int s, l, n;
        cin >> s >> l >> n;
        vector <string> str(s);
        for (int i = 0; i < s; i++) {
            cin >> str[i];
        }
        sort(all(str));
        map <string, int> mp;
        for (int i = 0; i < s; i++) {
            mp[str[i]] = i;
        }
        map <int, string> mp2;
        for (int i = 0; i < s; i++) {
            mp2[i] = str[i];
        }
        vector <vector <int>> w(s, vector <int> (s));
        for (int i = 0; i < l; i++) {
            string ss, tt; cin >> ss >> tt;
            w[mp[ss]][mp[tt]] = w[mp[tt]][mp[ss]] = 1;
        }
        vector <int> a(n);
        for (int i = 0; i < n; i++) {
            string ss; cin >> ss;
            a[i] = mp[ss];
        }
        vector <int> in(n), last(s, -1);
        vector <vector <int>> edge(n);
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < s; j++) {
                if (last[j] >= 0 && !w[a[last[j]]][a[i]]) {
                    ++in[i];
                    edge[last[j]].push_back(i);
                }
            }
            last[a[i]] = i;
        }
        priority_queue <node> q;
        for (int i = 0; i < n; i++) {
            if (in[i] == 0) {
                q.push(node{i, a[i]});
            }
        }
        vector <string> ans;
        while (!q.empty()) {
            node cur = q.top(); q.pop();
            ans.push_back(mp2[cur.val]);
            int u = cur.u;
            for (auto v : edge[u]) {
                if (--in[v] == 0) {
                    q.push(node{v, a[v]});
                }
            }
        }
        for (auto it : ans) cout << it << ' ';
    }
     
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cout << fixed << setprecision(20);
        run();
        return 0;
    }
    

    I. Rats

    签到。

    Code
    /*
     * Author:  heyuhhh
     * Created Time:  2020/5/21 13:39:18
     */
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    #include <cmath>
    #include <set>
    #include <map>
    #include <queue>
    #include <iomanip>
    #include <assert.h>
    #define MP make_pair
    #define fi first
    #define se second
    #define pb push_back
    #define sz(x) (int)(x).size()
    #define all(x) (x).begin(), (x).end()
    #define INF 0x3f3f3f3f
    #define Local
    #ifdef Local
      #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
      void err() { std::cout << std::endl; }
      template<typename T, typename...Args>
      void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
      template <template<typename...> class T, typename t, typename... A> 
      void err(const T <t> &arg, const A&... args) {
      for (auto &v : arg) std::cout << v << ' '; err(args...); }
    #else
      #define dbg(...)
    #endif
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    //head
    const int N = 1e5 + 5;
     
    void run() {
        int n1, n2, n12;
        cin >> n1 >> n2 >> n12;
        int ans = (n1 + 1) * (n2 + 1) / (n12 + 1) - 1;
        cout << ans << '
    ';
     
    }
     
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cout << fixed << setprecision(20);
        run();
        return 0;
    }
    

    J. Counting Trees

    题意:
    现有一颗树,每个结点上有个标号,并且满足如下性质,子节点的标号值不小于父亲结点。
    现在给出这棵树中序遍历的标号序列。
    问有多少棵树满足以上条件。

    思路:
    显然这棵树的根标号值最小,如果所有标号值各不相同,那么很显然方案数就为(1):每次根结点确定,左右子树递归处理。
    这给我们提供了一种思路:每次选择最小的作为根,然后分割过后递归进入子树处理。
    出现了个问题,如果有多个值最小怎么办?那么这些最小的值的深度肯定是尽可能小的,因为我们最开始的根都选择他们。这些最小值的方案数为卡特兰数。然后这些最小的数将序列分为几个部分,每个部分为一个子树的方案数,当我们最小的数的方案确定时,剩下的其子树的方案也就确定了(感受一下)。
    所以就有一个递归做法,序列分割为若干个部分过后递归下去,最后把所有结果乘起来即可。
    这样复杂度可能是(O(n^2)),代码量也略大。
    这是从小到大,我们可以考虑从大到小,显然最终一些数在一个连通块以内,那么他们中间就不可能出现小于的数,否则无论怎样都会被分割。那么可以根据这一点从大到小枚举数,然后确定其连通块,然后可以根据连通块中他们的个数直接计算答案。最后乘进答案就行。
    两种核心思想都是等价的,只是第二种想法进一步利用了“区间分割”这一性质,我们可以直接对每种数找到其连通块。
    代码如下:

    Code
    /*
     * Author:  heyuhhh
     * Created Time:  2020/5/21 15:22:22
     */
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    #include <cmath>
    #include <set>
    #include <map>
    #include <queue>
    #include <iomanip>
    #include <assert.h>
    #define MP make_pair
    #define fi first
    #define se second
    #define pb push_back
    #define sz(x) (int)(x).size()
    #define all(x) (x).begin(), (x).end()
    #define INF 0x3f3f3f3f
    #define Local
    #ifdef Local
      #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
      void err() { std::cout << std::endl; }
      template<typename T, typename...Args>
      void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
      template <template<typename...> class T, typename t, typename... A> 
      void err(const T <t> &arg, const A&... args) {
      for (auto &v : arg) std::cout << v << ' '; err(args...); }
    #else
      #define dbg(...)
    #endif
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    //head
    const int N = 2e6 + 5, MOD = 1e9 + 7;
     
    int fac[N], inv[N], INV[N];
    int qpow(ll a, ll b) {
        ll res = 1;
        while (b) {
            if (b & 1) res = res * a % MOD;   
            a = a * a % MOD;
            b >>= 1;
        }
        return res;
    }
     
    int C(int n, int m) {
        return 1ll * fac[n] * inv[m] % MOD * inv[n - m] % MOD;
    }
     
    int cat(int n) {
        return 1ll * C(2 * n, n) * INV[n + 1] % MOD;
    }
    int f[N][21];
    int n;
    void Get_st(){
        for(int j=1;j<=20;j++)
            for(int i=1;i<=n;i++)
                if(i+(1<<(j-1))<=n) f[i][j]=min(f[i][j-1],f[i+(1<<(j-1))][j-1]);
    }
    int Get_min(int l,int r){
        if (l > r) return INF;
        int k=0;
        while(1<<(k+1)<=r-l+1) k++;
        return min(f[l][k],f[r-(1<<k)+1][k]);
    } 
    vector <int> p[N];
     
    void run() {
        cin >> n;
        fac[0] = 1;
        for (int i = 1; i < N; i++) fac[i] = 1ll * fac[i - 1] * i % MOD;
        inv[N - 1] = qpow(fac[N - 1], MOD - 2);
        for (int i = N - 2; i >= 0; i--) inv[i] = 1ll * inv[i + 1] * (i + 1) % MOD;
        for (int i = N - 1; i >= 0; i--) INV[i] = qpow(i, MOD - 2);
        memset(f, INF, sizeof(f));
        for (int i = 1; i <= n; i++) {
            int x; cin >> x;
            f[i][0] = x;
            p[x].push_back(i);
        }
        Get_st();
        int ans = 1;
        for (int i = N - 1; i >= 0; i--) if (sz(p[i])) {
            int cnt = 1;
            for (int j = 1; j < sz(p[i]); j++) {
                int L = p[i][j - 1], R = p[i][j];
                if (Get_min(L + 1, R - 1) > i) {
                    ++cnt;
                } else {
                    if (cnt > 1) {
                        ans = 1ll * ans * cat(cnt) % MOD;
                    }
                    cnt = 1;
                }
            }
            if (cnt > 1) {
                ans = 1ll * ans * cat(cnt) % MOD;
            }
        }
        cout << ans << '
    ';
    }
     
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cout << fixed << setprecision(20);
        run();
        return 0;
    }
    

    K. Birdwatching

    题意:
    给定一颗有根树,并且给定一个关键点(t),问有多少点只有一条路径到达关键点(t),且这条路径为(u ightarrow t)

    思路:
    暴力的做法:

    • 对于每个点删除(u ightarrow t)这条边,然后直接(dfs)看能不能走到(t)

    显然时间复杂度为(O(n^2)),不能承受。
    考虑对于所有的点删除到(t)的这条边,将这样的点放入集合(s)中。显然如果(uin s),能够到达(vin s),那么(u)就不合法。
    注意到这是一个可达性的问题,我们可以考虑建反图,然后从(uin s)出发进行染色。
    若一个点只被自己染色,那么就说明这个点合法。否则被其他点染色就不合法。
    这样考虑复杂度还是没有变化,我们可以给每个点限制染色个数为(2),这样每个点至多被遍历两次,复杂度就降下来变为(O(n))了。
    也是一个很巧妙的题。

    Code
    /*
     * Author:  heyuhhh
     * Created Time:  2020/5/21 18:10:44
     */
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    #include <cmath>
    #include <set>
    #include <map>
    #include <queue>
    #include <iomanip>
    #include <assert.h>
    #define MP make_pair
    #define fi first
    #define se second
    #define pb push_back
    #define sz(x) (int)(x).size()
    #define all(x) (x).begin(), (x).end()
    #define INF 0x3f3f3f3f
    #define Local
    #ifdef Local
      #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
      void err() { std::cout << std::endl; }
      template<typename T, typename...Args>
      void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
      template <template<typename...> class T, typename t, typename... A> 
      void err(const T <t> &arg, const A&... args) {
      for (auto &v : arg) std::cout << v << ' '; err(args...); }
    #else
      #define dbg(...)
    #endif
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    //head
    const int N = 1e5 + 5;
     
    int n, m, t;
    vector <int> G[N];
    int c1[N], c2[N];
     
    void dfs(int u, int c) {
        if (u == t) return;
        if (c1[u] == -1) {
            c1[u] = c;
        } else if(c2[u] == -1) {
            if (c1[u] == c) return;
            c2[u] = c;
        } else return;
        for (auto v : G[u]) dfs(v, c);
    }
     
    void run() {
        cin >> n >> m >> t;
        memset(c1, -1, sizeof(c1));
        memset(c2, -1, sizeof(c2));
        for (int i = 1; i <= m; i++) {
            int u, v; cin >> u >> v;
            G[v].push_back(u);
        }
        for (auto it : G[t]) {
            dfs(it, it);
        }
        vector <int> ans;
        for (int i = 0; i < n; i++) if (c1[i] == i && c2[i] == -1) {
            ans.push_back(i);
        }
        cout << sz(ans) << '
    ';
        for (auto it : ans) {
            cout << it << '
    ';
        }
    }
     
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cout << fixed << setprecision(20);
        run();
        return 0;
    }
    
  • 相关阅读:
    JAVA SE 基础复习-虚拟机
    不错的博客
    如何分析问题
    由Contains开始的
    相关有用链接
    C++语法一二
    关于论文的些许想法
    C++中一些容易迷惑的语法点总结
    android中各种组件的生命周期问题
    android开源框架thinkinandroid相关研究
  • 原文地址:https://www.cnblogs.com/heyuhhh/p/12941654.html
Copyright © 2011-2022 走看看