2004上海区域赛 Asia Regional Shanghai 题解 (7/10)

第一次发题解瑟瑟发抖 Σ(゚д゚;)

HDU 1052 Tian Ji -- The Horse Racing

题意简述:田忌赛马,给出双方马的速度,赢一局得200铜钱,求最多得多少铜钱。

一开始按照题意想的二分图,后来发现是贪心 Σ(゚д゚;)

先把国王的马和田忌的马排序,塞进一个deque里

然后按照以下方法操作:

(1) 若田忌最快的马比国王最快的马快,则用田忌最快的马赢国王最快的马。

  设国王最快的马为 k ,田忌最快的马为 t ,且各有另一只马 k', t'

  有 k' ≤ k < t , t' ≤ t

  如果让 k 和 t' 比,k' 和 t 比

    a. t' ≤ k' 时,原来一胜一负/平,交换后一胜一负。

    b. k' < t' ≤ k 时,原来两胜,交换后一胜一负/平。

    c. t' > k 时,原来两胜,交换后两胜。

  因此交换不会使结果更优,得证。

(2) 若田忌最快的马比国王最快的马慢,则用田忌最慢的马输国王最快的马。

  因为无论用什么马跟国王的这只马比都会输,因此消耗掉己方最慢的马最优。

(3) 若田忌最快的马和国王的马一样快,且田忌最慢的马比国王最慢的马快,则用田忌最慢的马赢国王最慢的马。

  设国王最快的马为 k ,田忌最快的马为 t ,且各有另一只马 k', t'

  有 k < t ≤ t' , k ≤ k'

  如果让 k 和 t' 比,k' 和 t 比

    a. k' ≤ t 时,原来两胜,交换后一胜一平。

    b. t < k' ≤ t' 时,原来两胜/一胜一平,交换后一胜一负

    c. k' > t 时,原来一胜一负,交换后一胜一负

  因此交换不会使结果更优,得证。

(4) 若田忌最快的马和国王的马一样快,且田忌最慢的马比国王最慢的马慢或一样快,则用田忌最慢的马输国王最快的马。

  设国王最快的马为 k ,田忌最慢的马为 t ,且各有另一只马 k', t'

  有 t ≤ k' ≤ k , t ≤ t' ≤ k

  如果让 k 和 t' 比,k' 和 t 比

    a. k' ≤ t' 时,原来两负或一负一平,交换后两负。

    c. k' > t' 时,原来一胜一负,交换后两负。

  因此交换不会使结果更优,得证。

 

其实以上的证明并不严格,因为除了交换还能三轮换、四轮换,可能那样会使得结果更优,但是emmm... 这个结论是正确的(逃

时间复杂度O(n)

#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;
int king[10010],tj[10010],ans=0;
void comp(int t,int k){
    if(t<k) ans--;
    else if(t>k) ans++;
}
int cmp(int a,int b){
    return a>b;
}
int main(){
    int n,tfp,tep,kfp,kep;
    while(scanf("%d",&n)!=EOF&&n!=0){
        for(int i=0;i<n;i++){
            scanf("%d",&tj[i]);
        }
        for(int i=0;i<n;i++){
            scanf("%d",&king[i]);
        }
        sort(tj,tj+n,cmp);
        sort(king,king+n,cmp);
        tfp=kfp=ans=0;
        tep=kep=n-1;
        for(int i=0;i<n;i++){
            if(tj[tfp]<king[kfp]) {comp(tj[tep],king[kfp]); --tep,++kfp;}
            else if(tj[tfp]>king[kfp]) {comp(tj[tfp],king[kfp]); ++tfp,++kfp;}
            else if(tj[tep]>king[kep]) {comp(tj[tep],king[kep]); --tep,--kep;}
            else {comp(tj[tep],king[kfp]); --tep,++kfp;}
        }
        printf("%d\n",ans*200);
    }
    return 0;
}
AC Code

 

HDU 1661 Amphiphilic Carbon Molecules

看这个题只想到 O(n^3) 的做法,然后发现紫书上有这个题 QAQ

直接暴力方法是枚举所有的点对,判断所有点在线的哪边,枚举点对 O(n^2),判断所有点的位置 O(n),总共 O(n^3),对于1000的数据显然不能过

而扫描线法是枚举每一个点,按照极角将其他的点排序,让扫描线旋转一圈,每次碰到点的时候,让上一个点到线的另一侧,,一边分子数+1,另一边分子数-1,复杂度降为O(n^2*log n)

另外还有一个技巧:对于某一个固定的转轴,一点等价于与该点关于转轴中心对称的,极性与该点相反的点,因此可以把所有的纵坐标变成大于0的,可以简化一些代码。

#include <cstdio>
#include <algorithm>
//#include <cstring>
using namespace std;
typedef long long ll;
struct point {
    int x,y,pol;
    void invert(){
        x=-x,y=-y,pol=1-pol;
    }
} arr[1010],tmp[1010];
int tcnt[2],ncnt[2],olcnt[2];
bool cmp(point a,point b){
    if(a.x==0) return b.x<0;
    if(b.x==0) return a.x>0;
    if(a.x*b.x<0) return a.x>b.x;
    return a.y*b.x<b.y*a.x;
}
inline bool notequal(point a,point b){
    return cmp(a,b)||cmp(b,a);
}
int main(){
    int n,ptr,ans,ovl;
    while(scanf("%d",&n)!=EOF&&n!=0){
        ans=0;
        for(int i=0;i<n;i++){
            scanf("%d%d%d",&arr[i].x,&arr[i].y,&arr[i].pol);
        }
        for(int i=0;i<n;i++){
            ptr=ovl=0;
            tcnt[0]=tcnt[1]=olcnt[0]=olcnt[1]=0;
            for(int j=0;j<n;j++){
                if(arr[j].x==arr[i].x&&arr[j].y==arr[i].y){
                    ++ovl;
                    continue;
                }
                tmp[ptr].x=arr[j].x-arr[i].x;
                tmp[ptr].y=arr[j].y-arr[i].y;
                tmp[ptr].pol=arr[j].pol;
                if(tmp[ptr].y<0||(tmp[ptr].y==0&&tmp[ptr].x<0)) tmp[ptr].invert();
                ++tcnt[tmp[ptr].pol];
                ++ptr;
            }
            ncnt[0]=tcnt[0];
            ncnt[1]=tcnt[1];
            sort(tmp,tmp+n-1,cmp);
            for(int j=0;j<n-1;j++){
                if(j!=0&&notequal(tmp[j],tmp[j-1])){
                    ans=max(ans,max(tcnt[0]-ncnt[0]+ncnt[1]+olcnt[1],tcnt[1]-ncnt[1]+ncnt[0]+olcnt[0])+ovl);
                    olcnt[0]=olcnt[1]=0;
                }
                --ncnt[tmp[j].pol];
                ++olcnt[tmp[j].pol];
            }
            ans=max(ans,max(tcnt[0]-ncnt[0]+ncnt[1]+olcnt[1],tcnt[1]-ncnt[1]+ncnt[0]+olcnt[0])+ovl);
        }
        printf("%d\n",ans);
    }
    return 0;
}
AC Code

 

HDU 1662 Link and Pop -- the Block Game

题意简述:连连看,每个块在每次操作后会向指定的方向移动,模拟玩家的操作。

基本算是模拟题。。。慢慢写吧

判断两个块是否可以连接有 O(n*m) 的方法,开一个vis数组,把两者可以直线到达的位置打上标记。

  第一块打标记时顺便看找不找得到第二块,找得到就说明可以直线相连

  第二块打标记时找第一块的标记,找得到说明可以两条线相连

  然后每行每列扫一遍,如果发现有两个标记可以直线到达则说明可以三条线相连

坑点:线可以出界,也就是说像

1 3
AS BS AS

这样的数据里面两个A可以相连

时间复杂度应该是 O((nm)^3)

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
using namespace std;
typedef long long ll;
const int dirs[5][2]={
    {0,0},{-1,0},{1,0},{0,-1},{0,1}
};
int n,m,clk,minlc,mxi1,mxj1,mxi2,mxj2;
struct block {
    char name;
    int dir,updt,id;
    block(){name=dir=0;updt=-1;}
} arr[33][33];
int vis[33][33];
int loci[1000],locj[1000];
vector<int> ids[128];
bool isavail(int i,int j){
    return i>=0&&i<n&&j>=0&&j<m&&arr[i][j].updt==-1;
}
bool mkmove(int i,int j){
    if(arr[i][j].updt==clk) return false;
    if(arr[i][j].updt==-1) return false;
    int ni=i+dirs[arr[i][j].dir][0];
    int nj=j+dirs[arr[i][j].dir][1];
    if(isavail(ni,nj)){
        arr[ni][nj]=arr[i][j];
        arr[ni][nj].updt=clk;
        arr[i][j].updt=-1;
        loci[arr[ni][nj].id]=ni;
        locj[arr[ni][nj].id]=nj;
        return true;
    }
    return false;
}
int getdir(char ch){
    switch(ch){
        case 'U': return 1;
        case 'D': return 2;
        case 'L': return 3;
        case 'R': return 4;
        default: return 0;
    }
}
bool expand(int ii,int jj,int f,int v){
    for(int i=ii+1;i<n+2;i++){
        if(vis[i][jj]==f) return true;
        if(i!=0&&i!=n+1&&arr[i-1][jj-1].updt!=-1) break;
        vis[i][jj]=v;
    }
    for(int i=ii-1;i>=0;i--){
        if(vis[i][jj]==f) return true;
        if(i!=0&&i!=n+1&&arr[i-1][jj-1].updt!=-1) break;
        vis[i][jj]=v;
    }
    for(int j=jj+1;j<m+2;j++){
        if(vis[ii][j]==f) return true;
        if(j!=0&&j!=m+1&&arr[ii-1][j-1].updt!=-1) break;
        vis[ii][j]=v;
    }
    for(int j=jj-1;j>=0;j--){
        if(vis[ii][j]==f) return true;
        if(j!=0&&j!=m+1&&arr[ii-1][j-1].updt!=-1) break;
        vis[ii][j]=v;
    }
    return false;
}
int reachable(int i,int j,int ti,int tj){
    ++i,++j,++ti,++tj;
    if(arr[ti-1][tj-1].updt==-1) return 0;
    memset(vis,0,sizeof(vis));
    vis[ti][tj]=1;
    if(expand(i,j,1,2)) return 1;
    if(minlc==2) return 0;
    if(expand(ti,tj,2,3)) return 2;
    if(minlc==3) return 0;
    vis[ti][tj]=0;
    int ssign;
    for(int i=0;i<n+2;i++){
        ssign=0;
        for(int j=0;j<m+2;j++){
            if(i!=0&&j!=0&&i!=n+1&&j!=m+1&&arr[i-1][j-1].updt!=-1) ssign=0;
            if(vis[i][j]==2){
                if(ssign==0) ssign=2;
                else if(ssign==3) return 3;
            } else if(vis[i][j]==3) {
                if(ssign==0) ssign=3;
                else if(ssign==2) return 3;
            }
        }
    }
    for(int j=0;j<m+2;j++){
        ssign=0;
        for(int i=0;i<n+2;i++){
            if(i!=0&&j!=0&&i!=n+1&&j!=m+1&&arr[i-1][j-1].updt!=-1) ssign=0;
            if(vis[i][j]==2){
                if(ssign==0) ssign=2;
                else if(ssign==3) return 3;
            } else if(vis[i][j]==3) {
                if(ssign==0) ssign=3;
                else if(ssign==2) return 3;
            }
        }
    }
    return 0;
}
char buf[10];
void dispose(int i,int j){
    arr[i][j].updt=-1;
    loci[arr[i][j].id]=-1;
}
bool bigger(int i1,int j1,int i2,int j2){
    return i1==i2?j1>j2:i1>i2;
}
void print(){
    for(int i=0;i<n;i++){
        for(int j=0;j<m;j++){
            printf("%c",arr[i][j].updt==-1?'.':arr[i][j].name);
        }
        printf("\n");
    }
}
int main(){
    int nid,ct=0;
    bool flag;
    while(scanf("%d%d",&n,&m)==2&&n!=0){
        nid=clk=0;
        for(int i=0;i<128;i++) ids[i].clear();
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                scanf("%s",buf);
                arr[i][j].name=buf[0];
                arr[i][j].dir=getdir(buf[1]);
                arr[i][j].id=nid;
                arr[i][j].updt=0;
                loci[nid]=i;
                locj[nid]=j;
                ids[buf[0]].push_back(nid);
                ++nid;
            }
        }
        minlc=0;
        while(true){
            minlc=4;
            for(int i=0;i<n;i++){
                for(int j=0;j<m;j++){
                    if(arr[i][j].updt==-1) continue;
                    int idsl=ids[arr[i][j].name].size();
                    int tminlc=-1;
                    for(int k=0;k<idsl;k++){
                        if(ids[arr[i][j].name][k]==arr[i][j].id) continue;
                        if(loci[ids[arr[i][j].name][k]]==-1) continue;
                        int ni=loci[ids[arr[i][j].name][k]];
                        int nj=locj[ids[arr[i][j].name][k]];
                        if(bigger(i,j,ni,nj)) continue;
                        int nowlc=reachable(i,j,ni,nj);
                        if(nowlc&&(tminlc==-1||nowlc<tminlc||(nowlc==tminlc&&bigger(mxi2,mxj2,ni,nj)))){
                            mxi1=i;
                            mxj1=j;
                            mxi2=ni;
                            mxj2=nj;
                            minlc=nowlc+1;
                            tminlc=nowlc;
                        }
                    }
                    if(tminlc!=-1) minlc=tminlc;
                    if(minlc==1) goto goto_break;
                }
            }
            goto_break:;
            if(minlc==4) break;
            dispose(mxi1,mxj1);
            dispose(mxi2,mxj2);
            //print();
            //printf("\n");
            flag=true;
            while(flag){
                flag=false;
                ++clk;
                for(int i=0;i<n;i++){
                    for(int j=0;j<m;j++){
                        if(mkmove(i,j)) flag=true;
                    }
                }
            }
            //print();
            //printf("\n\n");
        }
        printf("Case %d\n",++ct);
        print();
    }
    return 0;
}
AC Code

 

HDU 1663 The Counting Problem

题意简述:求从m到n中0-9各出现了多少次。

简单的数位dp,dp[i]表示i位数中1-9的个数以及带前导零的i位数中0的个数,dp0[i]表示不带前导零的i位数中0的个数,转移方程

  dp[i]=dp[i-1]*10+10^(i-1)

  dp0[i]=dp0[i-1]+dp[i-1]*9

时间复杂度大概是O(log(n)+ log(m))

#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;
int dp[10],dp0[10],ans1[10],ans2[10],temp[10];
int pow(int a,int n){
    ll ans=1;
    for(int i=0;i<n;i++) ans*=a;
    return ans;
}
void init(){
    for(int i=1;i<10;i++){
        dp[i]=dp[i-1]*10+pow(10,i-1); 
        dp0[i]=dp0[i-1]+dp[i-1]*9;
    }
}
void solve(int n,int *arr){
    int dptr=1,cnt=0,flag=1;
    while(n/dptr>=10){
        ++cnt;
        dptr*=10;
    }
    arr[0]=dp0[cnt];
    for(int j=1;j<10;j++) arr[j]=dp[cnt];
    while(dptr){
        for(int i=flag;i<n/dptr;i++){
            arr[i]+=dptr;
            for(int i=0;i<10;i++) arr[i]+=dp[cnt];
        }
        flag=0;
        arr[n/dptr]+=n%dptr;
        n%=dptr;
        dptr/=10;
        --cnt;
    }
}
int main(){
    init();
    int a,b;
    while(scanf("%d%d",&a,&b)==2&&a!=0){
        if(a>b) swap(a,b);
        solve(b+1,ans1);
        solve(a,ans2);
        for(int i=0;i<10;i++) printf("%d%c",ans1[i]-ans2[i],i==9?'\n':' ');
    }
    return 0;
}
AC Code

 

HDU 1664 Different Digits

题意简述:给出一个数,求它的一个倍数,使得其各位数字的种类最少的前提下最小。

首先,可以证明,任何一个数都有不超过两种数字组成的答案,因为对任意n,对于集合 {1,11,111,...,(10^(n+1)-1)/9} 中的 n+1 个数,其中一定存在两个数 n1 n2 (n1 < n2) 模 n 余数相等,于是 n2 - n1 只由 0 和 1 组成,且为n的倍数,得证。

所以先看有没有只用1种数字组成的答案,再遍历所有的数字组合可能,bfs搜索余数,记录下搜索的路径,然后比较搜出的结果大小就ok了。

每轮bfs最多搜n步,因此时间复杂度O(n)。

#include <cstdio>
#include <algorithm>
#include <queue>
#include <cstring>
using namespace std;
typedef long long ll;
bool vis[100010];
int minpath[100010],dep[100010],patht[100010];
char str[100010],ans[100010];
int countdigit(int n){
    int dn=0,ans=0;
    while(n){
        dn|=1<<n%10;
        n/=10;
    }
    while(dn){
        if(dn&1) ++ans;
        dn>>=1;
    }
    return ans;
}
int main(){
    int n,t,depth,nmod,nnum,mnlen;
    queue<int> q;
    while(scanf("%d",&n)==1&&n!=0){
        t=countdigit(n);
        if(t==1){
            printf("%d\n",n);
            continue;
        }
        mnlen=0x3f3f3f3f;
        for(int i=1;i<10;i++){
            memset(vis,0,sizeof(vis));
            depth=nmod=0;
            while(!vis[nmod]&&depth<mnlen-1){
                vis[nmod]=true;
                nmod=(nmod*10+i)%n;
                ++depth;
            }
            if(nmod==0){
                mnlen=depth;
                nnum=i;
            }
        }
        if(mnlen!=0x3f3f3f3f){
            for(int j=0;j<mnlen;j++) printf("%d",nnum);
            printf("\n");
            goto nextloop;
        }
        if(t==2){
            printf("%d\n",n);
            continue;
        }
        mnlen=0x3f3f3f3f;
        for(int i=0;i<10;i++){
            for(int j=i+1;j<10;j++){
                memset(vis,0,sizeof(vis));
                q=queue<int>();
                depth=1;
                if(i!=0){
                    q.push(i);
                    vis[i]=true;
                    minpath[i]=0;
                    patht[i]=i;
                    dep[i]=0;
                }
                q.push(j);
                vis[j]=true;
                minpath[j]=0;
                patht[j]=j;
                dep[j]=0;
                q.push(-1);
                while(!vis[0]){
                    t=q.front();
                    q.pop();
                    if(q.empty()) break;
                    if(t==-1){
                        q.push(-1);
                        ++depth;
                        if(depth>mnlen) break;
                    } else {
                        int t1=(t*10+i)%n,t2=(t*10+j)%n;
                        if(!vis[t1]){
                            vis[t1]=true;
                            minpath[(t*10+i)%n]=t;
                            dep[t1]=depth;
                            patht[t1]=i;
                            q.push((t*10+i)%n);
                        }
                        if(!vis[t2]){
                            vis[t2]=true;
                            minpath[(t*10+j)%n]=t;
                            dep[t2]=depth;
                            patht[t2]=j;
                            q.push((t*10+j)%n);
                        }
                    }
                }
                if(vis[0]){
                    int ptr=0;
                    do {
                        str[dep[ptr]]=patht[ptr]+'0';
                        ptr=minpath[ptr];
                    } while(ptr);
                    str[dep[0]+1]='\0';
                    if(dep[0]<mnlen){
                        strcpy(ans,str);
                        mnlen=dep[0];
                    } else {
                        if(strcmp(ans,str)>0){
                            strcpy(ans,str);
                        }
                    }
                }
            }
        }
        printf("%s\n",ans);
        nextloop:;
    }
    return 0;
}
AC Code

 

HDU 1667 The Rotation Game

题意简述:不好概括。。。看原题吧

用迭代加深搜索 IDDFS 可解,由于一步最多只能向中心移入一个目标数字,所以搜索剩余步数小于中心非目标数字块的数量时剪枝。

用常量数组可以大幅简化代码,还有注意要找字典序最小的,所以搜到结果不要马上退出,要再看其他的数字会不会有字典序更小的。

时间复杂度是 O(8^n) , n 是答案也就是搜索深度,看起来很大但是有剪枝所以还是能过

#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
typedef long long ll;
int arr[24],route[100],route2[100];
const int rots[8][7]={
    {0,2,6,11,15,20,22},
    {1,3,8,12,17,21,23},
    {10,9,8,7,6,5,4},
    {19,18,17,16,15,14,13},
    {23,21,17,12,8,3,1},
    {22,20,15,11,6,2,0},
    {13,14,15,16,17,18,19},
    {4,5,6,7,8,9,10},
};
const int rev[8]={5,4,7,6,1,0,3,2};
const int ctr[8]={6,7,8,11,12,15,16,17};

void mkmove(int n){
    int temp=arr[rots[n][0]];
    for(int i=1;i<7;i++){
        arr[rots[n][i-1]]=arr[rots[n][i]];
    }
    arr[rots[n][6]]=temp;
}
int countctr(int n){
    int ans=0;
    for(int i=0;i<8;i++) if(arr[ctr[i]]==n) ++ans;
    return ans;
}
void print(){
    printf("  %d %d  \n",arr[0],arr[1]);
    printf("  %d %d  \n",arr[2],arr[3]);
    for(int i=4;i<11;i++) printf("%d",arr[i]);
    printf("\n  %d %d  \n",arr[11],arr[12]);
    for(int i=13;i<20;i++) printf("%d",arr[i]);
    printf("\n  %d %d  \n",arr[20],arr[21]);
    printf("  %d %d  \n\n",arr[22],arr[23]);
}
bool iddfs(int n,int dep,int limit){
    int cnt=countctr(n);
    bool flag=false;
    if(cnt==8) return true;
    if(8-cnt>limit-dep) return false;
    for(int i=0;i<8;i++){
        route[dep]=i;
        mkmove(i);
        if(iddfs(n,dep+1,limit)) flag=true;
        mkmove(rev[i]);
        if(flag) return true;
    }
    return false;
}
bool cmproute(int l){
    for(int i=0;i<l;i++){
        if(route[i]<route2[i]) return true;
        if(route[i]>route2[i]) return false;
    }
    return false;
}
int main(){
    int ans=-1,ansn;
    while(scanf("%d",&arr[0])!=EOF&&arr[0]!=0){
        ans=-1;
        for(int i=1;i<24;i++){
            scanf("%d",&arr[i]);
        }
        //print(); 
        for(int j=0;;j++){
            for(int k=1;k<4;k++){
                //printf("%d %d\n",k,j);
                if(iddfs(k,0,j)){
                    if(ans==-1){
                        //printf("ok!\n");
                        memcpy(route2,route,sizeof(route));
                        ans=j;
                        ansn=k;
                    } else {
                        //printf("try replace\n");
                        if(cmproute(ans)){
                            memcpy(route2,route,sizeof(route));
                            ansn=k;
                            //printf("ok!\n");
                        }
                    }
                }
            }
            if(ans!=-1) break;
        }
        for(int i=0;i<ans;i++) printf("%c",route2[i]+'A');
        if(ans==0) printf("No moves needed");
        printf("\n%d\n",ansn);
    }
    return 0;
}
AC Code

时限15000ms,这个代码327ms

 

HDU 1669 Jamie's Contact Groups

二分答案,然后做一对多的二分图多重匹配,写法和匈牙利算法相近,就是每一个电话簿都需要遍历其中所有元素找经过它们的增广路。

匈牙利算法的学习笔记

时间复杂度 O(mnlog(n))

#include <iostream>
#include <string>
#include <sstream>
#include <algorithm>
#include <vector>
#include <cstring>
using namespace std;
int n,m,limit;
bool vis[510];
int cont[510][1010];
vector<int> g[1010];
bool dfs(int k){
    for(auto i:g[k]){
        if(vis[i]) continue;
        vis[i]=true;
        if(cont[i][0]<limit){
            cont[i][++cont[i][0]]=k;
            return true;
        } else {
            for(int j=1;j<=limit;j++){
                if(dfs(cont[i][j])){
                    cont[i][j]=k;
                    return true;
                }
            }
        }
    }
    return false;
}
bool check(){
    for(int i=0;i<n;i++){
        memset(vis,0,sizeof(vis));
        if(!dfs(i)) return false;
    }
    return true;
}
int main(){
    int t;
    string buf,name;
    while(cin>>n>>m&&n!=0){
        getline(cin,buf);
        for(int i=0;i<n;i++){
            getline(cin,buf);
            istringstream sin(buf);
            sin>>name;
            g[i].clear();
            while(sin>>t){
                g[i].push_back(t);
            }
        }
        int ansl=1,ansr=n;
        while(ansl<ansr){
            memset(cont,0,sizeof(cont));
            limit=(ansl+ansr)/2;
            if(check()) ansr=limit;
            else ansl=limit+1;
        }
        cout<<ansl<<'\n';
    }
    return 0;
}
AC Code

 

posted @ 2020-04-26 16:47  whatss7  阅读(198)  评论(0)    收藏  举报