20160602常规赛总结
来源:互联网 发布:windows如何隐藏分区 编辑:程序博客网 时间:2024/05/18 01:19
Task1蛮有趣
Task2暴力dp==听老师讲了什么前缀和愣是没想通暴力的dp为什么要前缀和。。如果有前缀和我的dp就是O(n)了。。
Task3有一些问题
比如为什么关于开关问题同一个区间不会反转两次,虽然理由很有道理,但是我理解不通。。智商不够。。
那么以后只好记结论了
最后一题放一下题目讲一下思路。
图染色
Description
给定一个n个点,m条边的无向图。每条边都有一种颜色,’R’或者’B’;
每次染色可以选择一个点,把与这个相连的边的颜色都翻转。
求最少选择几个点进行染色,使得所有边的颜色最后都相同!
Solution
这个标点有点鬼。。
反正大概知道是开关问题了,那就很简单了。
首先枚举每个联通块的颜色。
并查集搞一下就差不多了。
怎么都觉得自己是第一次敲影子并查集。
[源代码]:
#include<iostream>#include<stdio.h>#include<string.h>#include<algorithm>#include<vector>using namespace std;#define pb push_back#define vec vector<int>const int M=4e5+5;struct node{int to;bool c;};vector<node>G[M];vec Nod;int n,m,fa[M],cnt[M];bool mark[M];inline void rd(int &a){ a=0;char c; while(c=getchar(),!isdigit(c)); do a=a*10+(c^48); while(c=getchar(),isdigit(c));}inline int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}inline void Min(int &a,int b){if(a==-1||a>b)a=b;}void dfs(int v,const bool clr){ mark[v]=1; Nod.pb(v); for(int i=0;i<G[v].size();++i){ node u=G[v][i]; if(u.c==clr){ int f1=find(v),f2=find(u.to); if(f1!=f2){ fa[f2]=f1; cnt[f1]+=cnt[f2]; } f1=find(v+n),f2=find(u.to+n); if(f1^f2){ fa[f2]=f1; cnt[f1]+=cnt[f2]; } } else{ int f1=find(v),f2=find(u.to+n); if(f1!=f2){ fa[f2]=f1; cnt[f1]+=cnt[f2]; } f1=find(v+n),f2=find(u.to); if(f1!=f2){ fa[f2]=f1; cnt[f1]+=cnt[f2]; } } if(!mark[u.to])dfs(u.to,clr); }}int main(){ int size = 256 << 20; // 256MB char *p = (char*)malloc(size) + size; __asm__("movl %0, %%esp\n" :: "r"(p)); cin>>n>>m; char s[2]; for(int i=1,a,b,c;i<=m;++i){ rd(a),rd(b);scanf("%s",s);c=s[0]=='B'; G[a].pb((node){b,(bool)c}),G[b].pb((node){a,(bool)c}); } int ans1=0,ans2=0; for(int i=1;i<=n;++i)fa[i]=i,fa[i+n]=n+i,cnt[i]=1; for(int i=1;i<=n;++i) if(!mark[i]){ Nod.clear(); int res1=-1; dfs(i,0); int ct=0; for(int j=0;j<Nod.size();++j){ if(Nod[j]==fa[Nod[j]])++ct; if(Nod[j]+n==fa[Nod[j]]+n)++ct; } if(ct==1)res1=M; else{ for(int j=0;j<Nod.size();++j){ int v=Nod[j]; if(fa[v]==v)Min(res1,cnt[v]); if(fa[v+n]==v+n)Min(res1,cnt[v+n]); fa[v]=v,fa[v+n]=v+n; cnt[v]=1,cnt[v+n]=0; mark[v]=0; } } Nod.clear(); dfs(i,1); int res2=-1; ct=0; for(int j=0;j<Nod.size();++j){ if(Nod[j]==fa[Nod[j]])++ct; if(Nod[j]+n==fa[Nod[j]]+n)++ct; } if(ct==1)res2=M; else{ for(int j=0;j<Nod.size();++j){ int v=Nod[j]; if(fa[v]==v)Min(res2,cnt[v]); if(fa[v+n]==n+v)Min(res2,cnt[v+n]); } } ans1+=res1; ans2+=res2; } cout<<min(ans1,ans2)<<endl; return 0;}
代码略长,略丑。。但是思路很简单咯。
0 0
- 20160602常规赛总结
- 20160527常规赛总结
- 20160606常规赛总结
- 20160609常规赛总结
- 20160615常规赛总结
- 20160618常规赛总结
- 20160619非常规赛总结
- 20160622常规赛总结
- 20160625常规赛总结
- 20160627常规赛总结
- 20160628非常规赛总结
- 20160708常规赛总结
- 20160709常规赛总结
- 20160711常规赛总结
- 20160712常规赛总结
- 20160713常规赛总结
- 20160715常规赛总结
- 20160717常规赛总结
- html格式标记与文本标记
- Javascript基础
- 16.6.3 How2j 关于eclipse快捷键和浮点数易错
- HeadFirst 设计模式学习之模板方法模式
- Java类加载与反射
- 20160602常规赛总结
- 笔试题
- uploadify上传文件前端配置
- 在Android项目中替换资源图片不起作用的解决方法
- html图片的加载及超链接
- feof()和EOF的用法—— C中文件结尾的判断
- 装最多水的容器
- 高并发量网站解决方案
- Underlying DBMS error [SDE.***]解决思路