Codeforces India Hack2016 653ABCED

Codeforces India Hack2016 653ABCED
通过数:2
Rating:1288
倒数第二题是后缀数组,倒数第一题没看,哪一天再厉害一点再做吧。

A:
简单题

#include <bits/stdc++.h>
using namespace std;
#define pb push_back
const int MAXN = 1000 + 5;
int a[MAXN], n;
vector<int>vc;
int main()
{
    while(scanf("%d", &n) != EOF) {
        for(int i = 0 ; i < n ; i++) scanf("%d", a + i);
        sort(a, a + n);
        for(int i = 0 ; i < n ; i++) vc.pb(a[i]);
        vector<int>::iterator newend = unique(vc.begin(), vc.end());
        vc.erase(newend, vc.end());
        int ok = 0;
        for(int i = 0 ; i < (int)vc.size() ; i++) {
            if(i < 2) continue;
            if(vc[i - 2] == vc[i] - 2 && vc[i - 1] == vc[i] - 1) {
                ok = 1;
                break;
            }
        }
        if(ok) puts("YES");
        else puts("NO");
    }
    return 0;
}

B:

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 26;
#define pb push_back
vector<int>e[MAXN + 5];
int H, m;
char s1[MAXN], s2[MAXN];
int ans;
void dfs(int u, int dep)
{
    if(dep == H) {
        ans++;
        return;
    }
    for(int i = 0 ; i < (int)e[u].size() ; i++) {
        dfs(e[u][i], dep + 1);
    }
}
int main()
{
    while(scanf("%d%d", &H, &m) != EOF) {
        for(int i = 0 ; i < MAXN ; i++) e[i].clear();
        for(int i = 0 ; i < m ; i++) {
            scanf("%s%s", s1, s2);
            e[s2[0] - 'a'].pb(s1[0] - 'a');
        }
        ans = 0;
        dfs(0, 1);
        printf("%d\n", ans);
    }
    return 0;
}

C:
/*
最多有几个不合法点是有限的,大约4-6个
然后在这些不合法的点里,枚举它和其余点交换的情况
交换后,最多影响6个点,看一看这6个点是否合法,合法后是否6个受影响的点覆盖了原不合法的点集
*/

#include <bits/stdc++.h>
using namespace std;
#define pb push_back
const int MAXN = 150000 + 5;
int a[MAXN], n;
vector<int>vc, e;
bool invc[MAXN];
bool valid(int u)
{
    if(u == n) return true;
    else if(u % 2 == 1 && a[u] >= a[u + 1]) return false;
    else if(u % 2 == 0 && a[u] <= a[u + 1]) return false;
    return true;
}
int solve(int mark, int i)
{
    swap(a[i], a[vc[mark]]);
    int ok = 1;
    if(!valid(i)) ok = 0;  // printf("i = %d, first ok = %d\n", i, ok);
    if(i > 1 && !valid(i - 1)) ok = 0;// printf("i = %d, second ok = %d\n", i, ok);
    if(!valid(vc[mark])) ok = 0;// printf("i = %d, third ok = %d\n", i, ok);
    if(vc[0] > 1 && !valid(vc[mark] - 1)) ok = 0;// printf("i = %d, forth ok = %d\n", i, ok);
//    puts("");
    if(ok) {
        if(!e.empty()) e.clear();
        for(int j = -1 ; j <= 1 ; j++) {
            e.pb(vc[mark] + j);
            e.pb(i + j);
        }
        sort(e.begin(), e.end());
        vector<int>::iterator newend = unique(e.begin(), e.end());
        e.erase(newend, e.end());
        int now = 0;
        for(int j = 0 ; j < (int)e.size() ; j++) {
            if(now == vc.size()) break;
            if(vc[now] == e[j]) now++;
        }
        if(now < vc.size()) ok = 0;
    }
    swap(a[i], a[vc[mark]]);
    return ok;
}
int main()
{
    while(scanf("%d", &n) != EOF) {
        if(!vc.empty()) vc.clear();
        for(int i = 1 ; i <= n ; i++) scanf("%d", a + i);
        memset(invc, false, sizeof invc);
        for(int i = 1 ; i < n ; i++) {
            if(!valid(i)) {
                vc.pb(i); vc.pb(i + 1);
                invc[i] = true; invc[i + 1] = true;
            }
        }
        sort(vc.begin(), vc.end());
        vector<int>::iterator newend = unique(vc.begin(), vc.end());
        vc.erase(newend, vc.end());

//        for(int i = 0 ; i < (int)vc.size() ; i++) printf("%d ", vc[i]);
//        printf("\n");
        if(vc.size() > 6) puts("0");    ///此处若写为4则WA
        else {
            int ans = 0;
            for(int mark = 0 ; mark < vc.size() ; mark++) {
                for(int i = 1 ; i <= n ; i++) {
                   if(invc[i]) continue;
                   if(solve(mark, i)) ans++;
                }
            }
            for(int mark = 0 ; mark < vc.size() ; mark++) {
                for(int j = mark + 1; j < vc.size() ; j++) {
                    if(solve(mark, vc[j])) ans++;
                }
            }
            printf("%d\n", ans);
        }
    }
    return 0;
}

D:
/*
二分快递员的载重量,然后可以知道每条边可以通行几个快递员
然后跑一遍网络流

值得注意的是最后二分判断的时候
用了循环次数而不是左右端点的差值大小来作为循环结束的条件
实现了二分次数的可控,同时保证了精度

*/

#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define inf (1000000007)
#define gmin(a,b) ((a) < (b) ? (a) : (b))
#define gmax(a,b) ((a) > (b) ? (a) : (b))
typedef pair<int,LL> pii;
const int MAXN = 50 + 5;
const int MAXM = 500 + 5;
const double eps = 1e-10;
vector<pii>e[MAXN];
int n, m, x;
LL num[MAXN];
queue<int>que;

int s, t;                       ///源点、汇点
int d[MAXN], vis[MAXN];         ///距起点距离,访问数组
int cnt;
int head[MAXN];
struct Edge                     ///此邻接表少add_edge函数,需要自己添加
{
    int v, flow, ne;            ///用flow表示残量
    Edge(){}
    Edge(int _u, int _v, int _flow){v = _v, ne = head[_u]; flow = _flow;}
}edge[MAXM * 2];
void addedge(int u, int v, int w)
{
    edge[cnt] = Edge(u, v, w);
    head[u] = cnt++;
    edge[cnt] = Edge(v, u, 0);
    head[v] = cnt++;
}
bool BFS(int s, int t)
{
    memset(vis, 0, sizeof(vis));
    while(!que.empty()) que.pop();
    vis[s] = 1;
    d[s] = 0;
    que.push(s);
    while(!que.empty()){
        int u = que.front();  que.pop();
//        printf("u = %d\n", u);
        for(int now = head[u] ; now != -1 ; now = edge[now].ne){
            int v = edge[now].v;
            if(!vis[v] && edge[now].flow > 0){
                vis[v] = 1;
                d[v] = d[u] + 1;
                que.push(v);
            }
        }
    }
    return vis[t];
}
int DFS(int u, int a)
{
//    printf("u = %d, a = %d\n", u, a);
    if(u == n || a == 0)
        return a;
    int flow = 0, f;
    for(int now = head[u] ; now != -1 ; now = edge[now].ne){
        int v = edge[now].v;
        if(d[v] == d[u] + 1 && (f = DFS(v, min(edge[now].flow, a)))){   ///用DFS来回溯对边进行操作
            edge[now].flow -= f;
            edge[now ^ 1].flow += f;
            flow += f;
            a -= f;
            if(a == 0)  break;
        }
    }
    return flow;
}
int Dinic()                                                     ///求最大流
{
    int ans = 0;
    while(BFS(s, t)){
        ans += DFS(s, inf);                                     ///进入起点时,设初始流量无限大
    }
    return ans;
}

inline bool check(double v)
{
    s = 1, t = n;
    cnt = 0;
    memset(head, -1, sizeof head);
    for(int i = 1 ; i <= n ; i++) {
        for(int j = 0 ; j < (int)e[i].size() ; j++) {
            pii p = e[i][j];
            LL temp = p.se / v;
//            if(temp < 0) printf("v = %f, i = %d, temp = %f\n", v, i, temp);
            int tmp = gmin(temp, inf);
            addedge(i, p.fi, tmp);
        }
    }
    int temp = Dinic();
//    printf("v = %f, temp = %d\n", v, temp);
    if(temp >= x) return true;
    else return false;
}
int main()
{
    while(scanf("%d%d%d", &n, &m, &x) != EOF) {
        for(int i = 1 ; i <= n ; i++) e[i].clear();

        int u, v;
        LL w;
        for(int i = 0 ; i < m ; i++) {
            scanf("%d%d%I64d", &u, &v, &w);
            e[u].pb(mp(v, w));
        }

        double left = 0, right = 1000000 + 1;
        for(int i = 0 ; i < 200 ; i++) {
            double mid = (right + left) / 2;
            if(check(mid)) left = mid;
            else right = mid;
        }
        printf("%.8f\n", right * x);
    }
    return 0;
}

E:
/*
基本抄标程
已经想到要在补图上做dfs,然后判断有几个连通子块是必须要通过节点1与全图连通的就可以
但是由于补图实在太过巨大不知道怎么处理*
标程给出一种十分简便优越做法
存储一个名叫remain的set,表示剩余的点集
每次查找remain里的点,与当前点是否有不可以相连的边
没有则算入下一次dfs的储备对象里,并且从remain中删除该节点
为了防止边访问边删除导致set出现错误的情况,先用一个临时的结构存储所有可能点,然后从结构中调用该点进行删除
*/

#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define mp make_pair
const int MAXN = 300000 + 5;
typedef pair<int,int> pii;
set<pii>forbit;
set<int>remain;
int n, m, k;
bool isok(int u, int v)
{
    if(u > v) swap(u, v);
    return forbit.find(mp(u, v)) == forbit.end();
}
void dfs(int u)
{
    vector<int>temp; temp.clear();
    for(int i : remain) if(isok(u, i)) temp.pb(i);
    for(int i : temp) remain.erase(i);
    for(int i : temp) dfs(i);
}
int main()
{
    while(scanf("%d%d%d", &n, &m, &k) != EOF) {
        forbit.clear(); remain.clear();
        int deg = n - 1;
        for(int i = 0 ; i < m ; i++) {
            int u, v;   scanf("%d%d", &u, &v);
            if(u > v) swap(u, v);
            forbit.insert(mp(u, v));
            if(u == 1) deg--;
        }

        if(deg < k) {
            puts("impossible");
            continue;
        }
        for(int i = 2 ; i <= n ; i++) remain.insert(i);
        int cnt = 0;
        for(int i = 2 ; i <= n ; i++) {
            if(remain.find(i) != remain.end() && isok(1, i)) {
                dfs(i);
                cnt++;
            }
        }
        if(cnt > k) puts("impossible");
        else puts("possible");
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值