洛谷春季 ACM 多校训练第二周

T123571 Misaka Network

 这题我犯了一个逻辑错误,人傻了,想了半天也没debug出来;

做法:

是这样一个逻辑问题,一个点不是控制点,就是如果有控制点连到它就行了。

但,一个点是控制点,不是说连到它的点不是控制点就行了,只要有一个连到它的控制点,那它就不是控制点。

标准错误解法:

这个想法就是,vis=1表示他是控制点,如果一个点不是控制点,那么他的所有邻居就是控制点。

这肯定是错了,如果他的邻居有其他控制点可以连到呢?那这个邻居就不是控制点。

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
#define pb push_back
bool vis[N];
int ans,in[N];
int n,m;
vector<int>e[N];
void toposort(){
  queue<int>Q;
  for(int i=1;i<=n;i++)if(in[i]==0)vis[i]=1,Q.push(i);
  while(!Q.empty()){
  int u=Q.front();Q.pop();
  if(vis[u])ans++;
  for(int i=0;i<e[u].size();i++){
  int v=e[u][i];
  if(!vis[u])vis[v]=1;
  if(--in[v]==0)Q.push(v);
  }
  }
}
int main(){
    scanf("%d %d",&n,&m);
    for(int i=1;i<=n;i++)in[i]=0,vis[i]=0;
    int a,b;
    while(m--){
    scanf("%d %d",&a,&b);
    e[a].pb(b);
    in[b]++;
    }
    ans=0;
    toposort();
    printf("%d\n",ans);
  return 0;
}
View Code

正确解法:逻辑正确;

如果一个点是控制点,那么他的所有邻居就不是控制点。这个是正确的逻辑;】

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
#define pb push_back
bool vis[N];
int ans,in[N];
int n,m;
vector<int>e[N];
void toposort(){
  queue<int>Q;
  for(int i=1;i<=n;i++)if(in[i]==0)Q.push(i);
  while(!Q.empty()){
  int u=Q.front();Q.pop();
  if(!vis[u])ans++;
  for(int i=0;i<e[u].size();i++){
  int v=e[u][i];
  if(!vis[u])vis[v]=1;
  if(--in[v]==0)Q.push(v);
  }
  }
}
int main(){
    scanf("%d %d",&n,&m);
    for(int i=1;i<=n;i++)in[i]=0,vis[i]=0;
    int a,b;
    while(m--){
    scanf("%d %d",&a,&b);
    e[a].pb(b);
    in[b]++;
    }
    ans=0;
    toposort();
    printf("%d\n",ans);
  return 0;
}
View Code

 

T123573 Schedule

中模拟:题意:给你一个课的时间,让你排一个课表,每次问你这天的课程;

做法:这题主要是不好表示,set<cla>course[N][7];表示第几周,第几天的课程;

然后插入遍历,本来想搞个优先队列,但是无法遍历,所以只能set;

#include <bits/stdc++.h>
using namespace std;
#define pb push_back
typedef long long ll;
typedef long double ldb;
const int N=1e4+5;
struct cla{string name;int st,et;
    cla(string s,int a,int b){name=s,st=a,et=b;}
    friend bool operator<(cla A,cla B){
    return A.et<B.et;
    }
};
bool cmp(cla A,cla B){ return A.et<B.et;}
set<cla>course[N][7];
int mp[350];
int main(){
    mp['o']=1,mp['u']=2,mp['e']=3,mp['h']=4,mp['r']=5;
    int n,q;string s;char day[10];
    scanf("%d",&n);
    getchar();
    for(int i=1;i<=n;i++){
    getline(cin,s);
    s[s.size()-1]='\0';
    int sw,ew,sl,el;
    while(scanf("%d-%d%s%d-%d\n",&sw,&ew,day,&sl,&el)==5){
    // char tmp=days[1];
    int d=mp[day[1]];
    for(int w=sw;w<=ew;w++){
    course[w][d].insert(cla(s,sl,el));
    }
    }
    if(i==n)q=sw;
    }

    while(q--){
    int w;
    scanf("%d %s",&w,day);
    int d=mp[day[1]];
    set<cla>::iterator it;
    for(it=course[w][d].begin();it!=course[w][d].end();it++)
   cout<<it->st<<"-"<< it->et <<" "<<it->name<<endl;
    // printf("%d-%d %s\n",course[w][d][i].s,course[w][d][i].e,course[w][d][i].s);
    // printf("\n");
    puts("");
    }
    // system("pause");
    return 0;
}
View Code

 

T123575 Anan and Minecraft

题意:给你两个图,判断是否联通同构;

做法:看明白以后这题真的是。。。。

其实判断是否联通同构真的很简单,每次读入u,v;

用一个cnt表示两个集合的差,那么每次加入u,v的话,看看另一个集合u,v是否联通。
如果联通,cnt--,否则cnt++;

#include<bits/stdc++.h>
using namespace std;
#define pb push_back
typedef long long ll;
const int N=2e5+5;
const int inf=0x3f3f3f3f;
int fa1[N],fa2[N];
int find1(int x){return fa1[x]==x?x:fa1[x]=find1(fa1[x]);}
int find2(int x){return fa2[x]==x?x:fa2[x]=find2(fa2[x]);}
void build1(int x,int y){int dx=find1(fa1[x]),dy=find1(fa1[y]);if(dx!=dy)fa1[dx]=dy;}
void build2(int x,int y){int dx=find2(fa2[x]),dy=find2(fa2[y]);if(dx!=dy)fa2[dx]=dy;}
int main(){
    int n,m;
    scanf("%d %d",&n,&m);
    for(int i=1;i<=n;i++)fa1[i]=fa2[i]=i;
    int u,v,op,cnt=0;
    while(m--){
    scanf("%d %d %d",&op,&u,&v);
    if(op==1){
    if(find2(u)!=find2(v))cnt--;
    else cnt++;
    build1(u,v);
    }
    else {
    if(find1(u)!=find1(v))cnt--;
    else cnt++;
    build2(u,v);
    }
    if(!cnt)puts("A");
    else puts("B");
    }

      return 0;
}
View Code

 

posted @ 2020-03-08 12:41  无声-黑白  阅读(330)  评论(0编辑  收藏  举报