您的位置:首页 > 其它

近期总结 - 图论相关 cf 936B / cf 949C /ZOJ 3999

2018-03-11 22:18 369 查看
/看了Irene的博文,深受感动,决定也来写点什么东西纪念一下/

/昨天给女队上课讲了bfs也不知道自己弄懂了没有/
最近codeforces rating忽上忽下,终于还是回来啦。
也越来越觉得图论非常有意思,虽然我还在图论外围摸爬滚打,但看起来真的很有趣呀。

下面直接上题:
Codeforces 936B(1B/2D)



第二次打div1,只做了一题就跑路了,本来愉快pretest passed了这题之后开心地睡觉了(大概只是比赛开始40分钟,因为C完全不会做)
但是刚躺下突然想起,哦!我好像错了!
幸运的是,即使只过了一题,还是只-8(rating1912)
昨天修程序才发现错得真是非常彻底。
题意:给定一张有向图,问能否找出一条从顶点开始到一个出度为0的点,路径的长度为偶数。
若有,输出win并还原路径
若不为偶数,如果能到一环,则输出Draw,否则输出Lose。

自己写了傻傻的dfs老半天,缝缝补补问题越来越多,拆东墙补西墙,
意外地还是过了,把一个点拆成两个点,偶数过和奇数过是两种情况。
(感谢栗酱让我明白了判断有没有环竟然是判断在不在栈内的(图论白学.jpg))#include<bits/stdc++.h>
using namespace std;
#define pb push_back
#define mem(a) memset(a,1,sizeof(a))
typedef long long ll;
typedef pair<int,int> pii;

const int mn=2e5+5;

int n,m;
int s;
vector<int> g[mn];
int vis[mn][2];
int p[mn][2];
int ins[mn][2];
int ans,choose;

vector<int> v;
void dfs(int x,int k){
ins[x][k%2]=1;
vis[x][k%2]=k;
for(int i:g[x]){
if (ins[i][(k+1)%2]) ans=max(1,ans);
if (vis[i][(k+1)%2]) continue;
else{
p[i][(k+1)%2]=x;
dfs(i,k+1);
}
}
if (g[x].size()==0&&k%2==0){
ans=k;
choose=x;
}
ins[x][k%2]=0;
}

int main() {
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
int u;
scanf("%d",&u);
for(int j=1;j<=u;j++){
int v;
scanf("%d",&v);
g[i].pb(v);
}
}
scanf("%d",&s);
dfs(s,1);
if (ans==1) puts("Draw");
else if (!ans) puts("Lose");
else{
v.clear();
puts("Win");
int now=choose;
v.pb(now);
whi
4000
le(ans>1){
//printf("%d ",now);
now=p[now][ans%2];
ans--;
v.pb(now);
}
reverse(v.begin(),v.end());
for(int i:v) printf("%d ",i);
}
return 0;
}啊啊,总之非常神奇,就ac了。

第三场div1
对于Codeforces 949C(1C),又是经典图论题。
题目贼长,简直窒息。又正好被上一题找规律打的头晕目眩。
然后这把就正式掉出div1了,弘毅大大却借这场成功上紫,从此阴阳两隔(弥天大雾)
题意:经过复杂变换后,可以得到一张有向图,任意在有向图上选择至少一个点,但必须使所有该点可达的点也全部被选中。
问最少能选几个点(并给出点集)。



又是自己写了半天dfs发现,哇,怎么怎么写怎么错。
突然想起原来还有强连通分量的板子,发现我竟然手写不出来。
板子看了看都有点忘记了,拿出了以前的几个程序看了看,哇,真神奇啊。
(学的比忘得快系列)
然后终于AC了。#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define mem(a) memset(a,0,sizeof(a))
typedef long long ll;
typedef pair<int,int> pii;
typedef vector<int> vi;

const int mn=1e5+5;

int n,m,h;
int a[mn],out[mn];
vector<pii> e;
vector<int> g[mn],v,ans;
int pre[mn],lowlink[mn],sccno[mn],dfsc,sccc;
vector<int> scc[mn];
stack<int> s;

void dfs(int u){
pre[u]=lowlink[u]=++dfsc;
s.push(u);
for(int i=0;i<g[u].size();i++){
int v=g[u][i];
if (!pre[v]){
dfs(v);
lowlink[u]=min(lowlink[u],lowlink[v]);
}else if (!sccno[v]){
lowlink[u]=min(lowlink[u],pre[v]);
}
}
if (lowlink[u]==pre[u]){
sccc++;
while(1){
int x=s.top();s.pop();
sccno[x]=sccc;
if (x==u) break;
}
}
}

void find_scc(){
dfsc=sccc=0;
mem(sccno);mem(pre);
for(int i=1;i<=n;i++) if(!pre[i]) dfs(i);
}

int main() {
scanf("%d%d%d",&n,&m,&h);
for(int i=1; i<=n; i++)
scanf("%d",&a[i]);
for(int i=1; i<=m; i++) {
int u,v;
scanf("%d %d",&u,&v);
if (u>v)
swap(u,v);
e.pb(pii(u,v));
}
sort(e.begin(),e.end());
e.erase(unique(e.begin(),e.end()),e.end());
for(int i=0; i<e.size(); i++) {
int u=e[i].first,v=e[i].second;
if ((a[u]+1)%h==a[v])
g[u].pb(v);
if ((a[v]+1)%h==a[u])
g[v].pb(u);
}
/*for(int i=1; i<=n; i++) {
printf("%d:",i);
for(int j:g[i])
printf("%d ",j);
puts("");
}*/
find_scc();
for(int i=1;i<=n;i++){
for(auto j:g[i]){
if (sccno[i]!=sccno[j]){
out[sccno[i]]=1;
}
}
scc[sccno[i]].pb(i);
}
for(int i=1;i<=sccc;i++){
if (!out[i]&&(ans.empty()||ans.size()>scc[i].size())) ans=scc[i];
}
//answer
printf("%d\n",ans.size());
for(int i:ans)
printf("%d ",i);
return 0;
}

幸运的是昨晚(今天早上codeforces round470)题目非常好,我又回来了,div1!
Trie树竟然还记得!佩服我自己。
2B坚信水题一条路可以走到底暴力卡常竟然过了。
以后有空学学字符串,在字符串方面简直小白了。

今天还和团队做了ZOJ Monthly January,2018
题目真的难到窒息了,发现我的队友真是强到爆炸,除了写模拟题只能划水的我……
写了个多项式洛必达法则就全程划水了……#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 10005;
#define pb push_back
typedef pair<int,int> pii;
typedef long long ll;

char s
,s1
;
int n,m;
ll x0;
ll su,sd;

vector<pii> u,d;//up / down

char *p;

ll gcd(ll a,ll b){
return !b?a:gcd(b,a%b);
}

pii getu(){
int u=1,v=0;
if (*p=='+') p++;
else if (*p=='-') u*=-1,p++;
if (*p!='x'){
u*=(*p)-'0';
p++;
}
if (*p=='+'||*p=='-'||*p==0) return pii(u,0);
else {
assert(*p=='x');
p++;
v++;
if (*p=='^'){
p++;
v=*p-'0';
p++;
}
}
return pii(u,v);
}

void luobida(){
vector<pii> t;
for(pii i:u) {
i.first*=i.second;
if(i.second) t.pb(pii(i.first,i.second-1));
}
u=t;
t.clear();
for(pii i:d) {
i.first*=i.second;
if(i.second) t.pb(pii(i.first,i.second-1));
}
d=t;
}

ll px0[10];

void getsum(){
su=sd=0;
for(pii &i:u){
su+=i.first*px0[i.second];
}
for(pii &i:d){
sd+=i.first*px0[i.second];
}
}

int main() {
int t; scanf("%d", &t);
while (t--) {
u.clear();d.clear();
scanf("%s%s",s,s1);
p=s;
while(*p!=0) u.pb(getu());
p=s1;
while(*p!=0) d.pb(getu());
scanf("%lld",&x0);
px0[0]=1;
for(int i=1;i<=9;i++) px0[i]=px0[i-1]*x0;
getsum();
while(!sd&&!su){
luobida();
getsum();
}
if (!sd){
puts("INF");
continue;
}
if (!su){
puts("0");
continue;
}
ll g=gcd(su,sd);
su/=g,sd/=g;
if (sd<0){
su*=-1;
sd*=-1;
}
if (sd==1) printf("%lld\n",su);
else printf("%lld/%lld\n",su,sd);
}
}想好好学学图论和工具了,
发现原来自己真的什么都不懂啊……



加油!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: