黑色星期一 ----- 国庆训练翻车回忆录

      赛前翻车真酸爽,还有几天就哈尔滨站了,居然搞成这样子。

      训练赛的整个节奏被卡在一个D题,题目出发点搞错了,WA 31之后觉得思路没问题但思路就是有问题。

D:Problem D Denouncing Mafia

         题目大意:一棵树找k条链使得总点数最多。

            起初想的是,只要摘下  叶子数-k个小链就可以,但是不知道那出错了,正解的思路是,预处理出每条链被删掉之后,形成的森林集合,再从集合中选择最长的。

          

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int MAXN = 1e5+4;
vector<int>v[MAXN],s[MAXN];
int maxx[MAXN];
struct node
{
    int v,val;
    node(){}
    node(int a,int b){
        v = a;val = b;
    }
    bool operator < (const node & r)const{
        return val<r.val;
    }
};
void dfs(int x)
{
    maxx[x] = 1;
    int vv=0,Max = 0;
    int len = v[x].size();
    for(int i=0;i<len;i++){
        int to = v[x][i];
        dfs(to);
        if(maxx[to] + 1 >= maxx[x]){
            maxx[x] = maxx[to] + 1;
            vv = to;
        }
    }
   // cout<<x<<" * "<<vv<<endl;
    for(int i=0;i<len;i++){
        int to = v[x][i];
        if(to!=vv){
            s[x].push_back(to);
            //cout<<x<<" <-- "<<to<<endl;
        }
        else{
            int len2 = s[to].size();
            for(int j=0;j<len2;j++){
                int tt = s[to][j];
                s[x].push_back(tt);
                //cout<<x<<"  +  "<<tt<<" - "<<to<<endl;
            }
        }
    }
}
priority_queue<node>q;
int main()
{
    int n,k;
    scanf("%d%d",&n,&k);
    for(int i=2;i<=n;i++){
        int x;
        scanf("%d",&x);
        v[x].push_back(i);
    }
    dfs(1);
    q.push(node(1,maxx[1]));
//    for(int i=1;i<=n;i++){
//        int len = s[i].size();
//        cout<<i<<" : ";
//        for(int j=0;j<len;j++){
//            cout<<s[i][j]<<" ";
//        }
//        cout<<endl;
//    }
//    cout<<endl;
    int ans = 0;
    while(k--)
    {
        node now = q.top();
        q.pop();
        ans += now.val;
        int len = s[now.v].size();
        for(int i=0;i<len;i++){
            int to = s[now.v][i];
            q.push(node(to,maxx[to]));
        }
    }
    printf("%d\n",ans);
}

J  . Problem J Jar of Water Game

题目大意:很无脑的模拟,也不算很大,比赛期间题目都没有读,至少比D题简单很多。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
int n,k,w,now;
char C[100][10];
vector<char>v[50];
bool vis[50];
int num[20];
int id[500];
bool is_win(int x)
{
    if(w!=x && v[x].size() == 4 && v[x][0] == v[x][1] && v[x][1] == v[x][2] && v[x][2] == v[x][3])return 1;
    else return 0;
}
bool cmp(char x,char y)
{
    if(num[ id[x] ]  == num[ id[y] ] ){
        return id[x] < id[y];
    }
    return num[ id [x] ] < num[ id[y] ];
}
char ask(int x)
{
    memset(num,0,sizeof(num));
    for(int i=0;i<v[x].size();i++){
        num[ id[v[x][i]] ]++;
    }
    sort(v[x].begin(),v[x].end(),cmp);
//    cout<<" ---- "<<endl;
//    for(int i=0;i<v[x].size();i++){
//        cout<<v[x][i];
//    }
//    cout<<endl;
//    cout<<" ----- "<<endl;
    return v[x][0];
}
void init()
{
    id['A'] = 1; id['2'] = 2;id['3'] = 3;id['4'] = 4;
    id['5'] = 5; id['6'] = 6;id['7'] = 7;id['8'] = 8;
    id['9'] = 9; id['D'] = 10;id['Q'] = 11;id['J'] = 12;
    id['K'] = 13;
}
int main()
{
    init();
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++){
        scanf("%s",C[i]+1);
        for(int j=1;j<=4;j++){
            v[i].push_back(C[i][j]);
        }
    }
    int winner ;
    for(int i=1;i<=n;i++){
        if(i == k)continue;
        if(is_win(i)){
            printf("%d\n",i);
            return 0;
        }
    }
    w = now = k;vis[k] = 1;
    while(1){
//            cout<<endl;
//        cout<<now<<endl;
//        for(int i=0;i<v[now].size();i++){
//            cout<<v[now][i];
//        }
//        cout<<endl;
//        cout<<"w : "<<w<<endl;
        if(!vis[now] && w == now){
            w = (now == n)?1:now+1;
            vis[w] = 1;
            if(is_win(1)){
                printf("%d\n",1);
                return 0;
            }
            if(is_win(now)){
                printf("%d\n",now);
                return 0;
            }
            now = (now == n)?1:now+1;
            continue;
        }
        else{
            char ch = ask(now);
//            cout<<"ch : "<<ch<<endl;
            v[now].erase(v[now].begin());
            int b = (now == n)?1:now+1;
            v[b].push_back(ch);
        }
        vis[now] = 0;
        if(is_win(1)){
            printf("%d\n",1);
            return 0;
        }
        if(is_win(now)){
            printf("%d\n",now);
            return 0;
        }
        now = (now == n)?1:now+1;
    }
}

G。Problem G Getting Confidence

题目大意:一个矩阵,每行且每列取一个数,使得乘积最大。

                 这种每行每列的的题首先想到的就应该是网络流,取log乘积转加和就好了。

                列  -->  行

至于路径,只要找到正向流量为0的就好了。

#include <bits/stdc++.h>
using namespace std;
const int N=1e5+50;
const int INF=0x3f3f3f3f;
const double DINF=1.0*1e18;
const double eps=1e-8;
struct Edge{
    int u,v,w;
    double c;
    int next;
}e[N];
int ns,n,mt[105][105];
int cnt,head[N];
void init(){
    cnt=0;
    memset(head,-1,sizeof(head));
}
void add(int u,int v,int w,double c){
    e[cnt]=Edge{u,v,w,c,head[u]};
    head[u]=cnt++;
    e[cnt]=Edge{v,u,0,-c,head[v]};
    head[v]=cnt++;
}
double d[N];
int inq[N],s,t,p[N],a[N];
bool bf(int &flow,double &cost){
    for(int i=0;i<ns;i++){
        d[i]=DINF;
        inq[i]=0;
    }
    d[s]=0;
    p[s]=0;
    a[s]=INF;
    queue<int> q;
    q.push(s);
    inq[s]=1;
    while(!q.empty()){
        int u=q.front();
        q.pop();
        inq[u]=false;
        for(int i=head[u];i!=-1;i=e[i].next){
            int v=e[i].v;
            int w=e[i].w;
            double c=e[i].c;
            if(w>0 && d[v]>d[u]+c){
                d[v]=d[u]+c;
                p[v]=i;
                a[v]=min(a[u],w);
                if(!inq[v]){
                    q.push(v);
                    inq[v]=1;
                }
            }
        }
    }
    if(fabs(d[t]-DINF)<eps){
        return 0;
    }
    flow+=a[t];
    cost+=d[t]*a[t];
    for(int u=t;u!=s;u=e[p[u]].u){
        e[p[u]].w-=a[t];
        e[p[u]^1].w+=a[t];
    }
    return 1;
}
void mcmf(int &flow,double &cost){
    flow=0;
    cost=0.0;
    while(bf(flow,cost));
}
int main(){
    //freopen("in.txt","r",stdin);
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            scanf("%d",&mt[i][j]);
        }
    }
    ns=2*n+2;
    s=0,t=ns-1;
    init();
    for(int i=1;i<=n;i++){
        add(s,i,1,0.0);
    }
    for(int i=1;i<=n;i++){
        add(n+i,t,1,0.0);
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            add(i,n+j,1,-log10(mt[j][i]));
        }
    }
    int flow=0;
    double cost=0;
    mcmf(flow,cost);
    for(int i=1;i<=n;i++){
        for(int j=head[i];j!=-1;j=e[j].next){
            if(e[j].w==0){
                printf("%d",(e[j].v)-n);
                if(i==n){
                    printf("\n");
                }else{
                    printf(" ");
                }
                break;
            }
        } 
    }
    return 0;
}

真的不知道自己在干嘛,真懵逼。

I self-criticism three thousand ! ! !

I self-criticism three thousand ! ! !

I self-criticism three thousand ! ! !

I self-criticism three thousand ! ! !

I self-criticism three thousand ! ! !

I self-criticism three thousand ! ! !

I self-criticism three thousand ! ! !

I self-criticism three thousand ! ! !

I self-criticism three thousand ! ! !

I self-criticism three thousand ! ! !

I self-criticism three thousand ! ! !

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值