2019ICPC 上海现场赛

网址:https://ac.nowcoder.com/acm/contest/4370

B. Prefix Code

阅读理解,用个set维护下就行

#include <stdio.h>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <map> 
#include <stack>
#include <sstream>
#include <set>
// #pragma GCC optimize(2)

//#define int long long
#define ls u<<1
#define rs u<<1|1
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define REP(i,a,n) for(int i=a;i>=n;--i)
#define rush() int T;scanf("%d",&T);for(int Ti=1;Ti<=T;++Ti)
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define mm(i,v) memset(i,v,sizeof i);
#define mp(a, b) make_pair(a, b)
#define pi acos(-1)
#define fi first
#define se second

using namespace std;
typedef long long ll;
typedef double db;
typedef pair<ll, ll > PII;
priority_queue< PII, vector<PII>, greater<PII> > que;
stringstream ssin; //  ssin << string   while ( ssin >> int)
const ll LINF = 0x7fffffffffffffffll;

const int N = 4e5 + 5, M = 4e5 + 5, mod = 1e9 + 7, INF = 0x3f3f3f3f;
int _, n;
string s, t;
set<string>s1, s2;
vector<string>vec;

inline ll read() {
    char c=getchar();ll x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
    return x*f;
}


int main()
{
    #ifndef ONLINE_JUDGE
        freopen("in.txt","r",stdin);
        freopen("out.txt","w",stdout);
    #endif

    int cas = 0;
    _ = read();
    while (_--) {
        s1.clear();
        s2.clear();
        vec.clear();

        n = read();
        bool f = 1;
        rep(i, 1, n) {
            cin >> s;
            if (s1.find(s) != s1.end()) f = 0;
            s1.insert(s);
            vec.push_back(s);
        }
        rep(i, 0, n - 1) {
            s = vec[i];
            t.clear();
            for (int i = 0; i < s.size() - 1; ++i) {
                t += s[i];
                if (s1.find(t) != s1.end()) {
                    f = 0;
                    break;
                }
                if (!f) break;
            }
            if (!f) break;
        }
        printf("Case #%d: ", ++cas);
        if (f) puts("Yes");
        else puts("No");
    }

    // #ifndef ONLINE_JUDGE
    //     system("pause");
    // #endif
}

K. Color Graph

二分图签到

题意可以转化为判奇环,可以发现n很小,二进制枚举每个点的状态,然后直接判断即可

#include <stdio.h>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <map> 
#include <stack>
#include <sstream>
#include <set>
#pragma GCC optimize(2)

//#define int long long
#define mm(i,v) memset(i,v,sizeof i);
#define mp(a, b) make_pair(a, b)
#define pi acos(-1)
#define fi first
#define se second
//你冷静一点,确认思路再敲!!! 

using namespace std;
typedef long long ll;
typedef pair<int, int > PII;
priority_queue< PII, vector<PII>, greater<PII> > que;
stringstream ssin; //  ssin << string   while ( ssin >> int)

const int N = 500, mod = 1e9 + 9, INF = 0x3f3f3f3f;
int t, n, m, idx, id, pos, Max;
int e[N], h[N], ne[N], col[20];
bool flag;

inline int read(){
    char c=getchar();int x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
    return x*f;
}

void add(int a, int b) {
    e[idx] = b;
    ne[idx] = h[a];
    h[a] = idx++;
}

vector<PII> vec;
int main()
{
    cin >> t;
    while (t--) {
        vec.clear();
        Max = -1;
        mm(h, -1);
        idx = 0;
        cin >> n >> m;
        for (int i = 1; i <= m; ++i) {
            int a, b;
            cin >> a >> b;
            vec.push_back(mp(a, b));
        }
        for (pos = 0; pos <= (1 << n); ++pos) {
            mm(col, 0);
            flag = 1;
            for (int i = 1; i <= n; ++i) {
                if ((pos >> i) & 1 && !col[i]) {
                    col[i] = 1;
                }
            }
            int ans = 0;
            for (int i = 0; i < vec.size(); ++i) {
                int x = vec[i].first, y = vec[i].second;
                if (col[x] != col[y]) ans++;
            }
            Max = max(Max, ans);
            
        }
        printf("Case #%d: %d
", ++id, Max);
    }
    // system("pause");
    return 0;
}

E. Cave Escape

可以发现起点和终点并不影响选择的路径,所以只需要对点建边求最大生成树即可

#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
const int man = 1e3+10;
#define IOS ios::sync_with_stdio(0)
template <typename T>
inline T read(){T sum=0,fl=1;int ch=getchar();
for(;!isdigit(ch);ch=getchar())if(ch=='-')fl=-1;
for(;isdigit(ch);ch=getchar())sum=sum*10+ch-'0';
return sum*fl;}
template <typename T>
inline void write(T x) {static int sta[35];int top=0;
do{sta[top++]= x % 10, x /= 10;}while(x);
while (top) putchar(sta[--top] + 48);}
template<typename T>T gcd(T a, T b) {return b==0?a:gcd(b, a%b);}
template<typename T>T exgcd(T a,T b,T &g,T &x,T &y){if(!b){g = a,x = 1,y = 0;}
else {exgcd(b,a%b,g,y,x);y -= x*(a/b);}}
#ifndef ONLINE_JUDGE
#define debug(fmt, ...) {printf("debug ");printf(fmt,##__VA_ARGS__);puts("");}
#else
#define debug(fmt, ...)
#endif
typedef long long ll;
const ll mod = 1e9+7;
int x[man*man],fa[man*man],va[man][man];
int sz[man*man];
vector<pair<int,int> >A[10010];
int find(int x){
    return x == fa[x] ? x : fa[x] = find(fa[x]);
}
/*
int find(int x){
    int p = x;
    while(p!=fa[p])p = fa[p];
    while(x!=p){
        int tp = fa[x];
        fa[x] = p;
        x = tp;
    }
    return p;
}*/
 
bool _union(int u,int v){
   // cout << u << " 1" " << v <<endl;
    u = find(u);
    v = find(v);
  //  cout << u << " 2" " << v << endl;
    if(u==v)return true;
    if(sz[u]>sz[v]){
        sz[u] += sz[v];
        fa[v] = u;
    }else fa[u] = v,sz[v] += sz[u];
    return false;
}
 
int main() {
    #ifndef ONLINE_JUDGE
        //freopen("in.txt", "r", stdin);
        //freopen("out.txt","w",stdout);
    #endif
    int t;
    scanf("%d",&t);
    int T = 0;
    while(t--){
        int n,m,s,a,b,c,p;
        for(int i = 0;i <= 10000;i++)A[i].clear();
        scanf("%d%d%d%d%d%d",&n,&m,&s,&s,&s,&s);
        scanf("%d%d%d%d%d%d",x+1,x+2,&a,&b,&c,&p);
        fa[1] = 1;
        fa[2] = 2;
        for(int i = 3;i <= n*m;i++){
            fa[i] = i;
            sz[i] = 1;
            x[i] = (a*x[i-1] + b*x[i-2] + c)%p;
        }
        int cnt = 0;
        for(int i = 1;i <= n;i++){
            for(int j = 1;j <= m;j++){
                va[i][j] = x[(i-1)*m + j];
                if(!va[i][j])continue;
                if(i>1&&va[i-1][j])A[va[i][j]*va[i-1][j]].push_back(make_pair((i-1)*m + j,(i-2)*m + j));
                if(j>1&&va[i][j-1])A[va[i][j]*va[i][j-1]].push_back(make_pair((i-1)*m + j,(i-1)*m + j - 1));
            }
        }

        ll ans = 0;
        int res = 0;
        for(int j = 10000;j >= 0;j--){
            for(int i = 0;i < A[j].size();i++){
                int u = A[j][i].first;
                int v = A[j][i].second;
                //cout << A[i].w << endl;
                // if(!_union(u,v)){
                // }
                if (find(u) == find(v)) continue;
                int pa = find(u), pb = find(v);
                fa[pa] = pb;
                ans += j;
                res++;
                if(res==n*m-1)break;
            }
            if(res==n*m-1)break;
        }
         
        printf("Case #%d: %lld
",++T,ans);
    }
    return 0;
}

H. Tree Partition

二分+贪心

对于每棵树一定是去掉最大的子树最优

#include <stdio.h>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <map> 
#include <stack>
#include <sstream>
#include <set>
// #pragma GCC optimize(2)

//#define int long long
#define ls u<<1
#define rs u<<1|1
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define REP(i,a,n) for(int i=a;i>=n;--i)
#define rush() int T;scanf("%d",&T);for(int Ti=1;Ti<=T;++Ti)
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define mm(i,v) memset(i,v,sizeof i);
#define mp(a, b) make_pair(a, b)
#define pi acos(-1)
#define fi first
#define se second

using namespace std;
typedef long long ll;
typedef double db;
typedef pair<ll, ll > PII;
priority_queue< PII, vector<PII>, greater<PII> > que;
stringstream ssin; //  ssin << string   while ( ssin >> int)
const ll LINF = 0x7fffffffffffffffll;

const int N = 4e5 + 5, M = 4e5 + 5, mod = 1e9 + 7, INF = 0x3f3f3f3f;
int _, n, k, idx;
int e[M], ne[M], h[N];
int flag, cnt;
ll sum[N], a[N];

inline ll read() {
    char c=getchar();ll x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
    return x*f;
}

void add(int a, int b) {
    e[idx] = b;
    ne[idx] = h[a];
    h[a] = idx++;
}

void dfs(int u, int fa, ll mid) {
    sum[u] = a[u];
    if (sum[u] > mid || flag) {
        flag = 1;
        return;
    }

    for (int i = h[u]; ~i; i = ne[i]) {
        int v = e[i];
        if (v == fa) continue;
        dfs(v, u, mid);
        sum[u] += sum[v];
    }

    if (sum[u] > mid) {
        vector<ll>vec;
        for (int i = h[u]; ~i; i = ne[i]) {
            int v = e[i];
            if (v == fa) continue;
            vec.push_back(sum[v]);
        }
        sort(vec.begin(), vec.end());
        for (int i = vec.size() - 1; i >= 0; --i) {
            if (sum[u] <= mid) break;
            sum[u] -= vec[i];
            cnt++;
        }
    }
    if (cnt > k - 1) {
        flag = 1;
    }
}

bool ck(ll mid) {
    cnt = flag = 0;
    dfs(1, -1, mid);
    if (flag) return false;
    return true;
}

int main()
{
    #ifndef ONLINE_JUDGE
        freopen("in.txt","r",stdin);
        freopen("out.txt","w",stdout);
    #endif
    _ = read();
    ll cas = 0, ans;
    while (_--) {
        n = read(); k = read();
        idx = 0;
        for (int i = 0; i <= n; ++i) h[i] = -1;
        rep(i, 1, n - 1) {
            int u, v;
            u = read(); v = read();
            add(u, v);
            add(v, u);
        }
        rep(i, 1, n) a[i] = read();

        ll l = 0ll, r = 1e14;
        while (l < r) {
            ll mid = l + r >> 1;
            if (ck(mid)) {
                r = mid;
                ans = mid;
            } else {
                l = mid + 1;
            }
        }

        printf("Case #%lld: %lld
", ++cas, l);
    }

    // #ifndef ONLINE_JUDGE
    //     system("pause");
    // #endif
}

D. Spanning Tree Removal

构造,对于每棵树 i,i + 1, i - 1, i + 2, i - 2, i + 3, i - 2......

#include <stdio.h>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <map> 
#include <stack>
#include <sstream>
#include <set>
// #include <unordered_set>
// #pragma GCC optimize(2)

//#define int long long
#define ls u<<1
#define rs u<<1|1
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define REP(i,a,n) for(int i=a;i>=n;--i)
#define rush() int T;scanf("%d",&T);for(int Ti=1;Ti<=T;++Ti)
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define mm(i,v) memset(i,v,sizeof i);
#define mp(a, b) make_pair(a, b)
#define pi acos(-1)
#define fi first
#define se second

using namespace std;
typedef long long ll;
typedef double db;
typedef pair<ll, ll > PII;
priority_queue< PII, vector<PII>, greater<PII> > que;
stringstream ssin; //  ssin << string   while ( ssin >> int)
const ll LINF = 0x7fffffffffffffffll;

const int N = 1e3 + 5, M = 4e5 + 5, mod = 1e9 + 7, INF = 0x3f3f3f3f;
int _, n;
vector<PII>vec;
bool vis[N];

inline ll read() {
    char c=getchar();ll x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
    return x*f;
}

int main()
{
    #ifndef ONLINE_JUDGE
        freopen("in.txt","r",stdin);
        freopen("out.txt","w",stdout);
    #endif
    int cas = 0;
    _ = read();
    while (_--) {
        n = read();
        printf("Case #%d: %d
", ++cas, n / 2);
        rep(i, 1, n / 2) {
            int now = i - 1;
            printf("%d %d
", now % n + 1, (now + 1) % n + 1);
            for (int j = 2; j <= n - 1; ++j) {
                if (j & 1) printf("%d %d
", (now - j / 2 + n) % n + 1, (now + j / 2 + 1) % n + 1);
                else printf("%d %d
", (now + j / 2) % n + 1, (now - j / 2 + n) % n + 1);
            }
        }
    }
    // #ifndef ONLINE_JUDGE
    //     system("pause");
    // #endif
}
原文地址:https://www.cnblogs.com/mwh123/p/14044756.html