vis

「SNOI2019」通信 分治优化费用流建图

删除回忆录丶 提交于 2019-11-30 00:04:15
题意: n 个排成一列的哨站要进行通信。第 i 个哨站的频段为 a i 。 每个哨站 i i 需要选择以下二者之一: 1.直接连接到控制中心,代价为 W ; 2.连接到前面的某个哨站 j (j<i),代价为 |ai−aj|。 每个哨站只能被后面的至多一个哨站连接。 请你求出最小可能的代价和。 题解: 显然的费用流 然后我耿直的n^2建边,觉得我的费用流很快,应该可以过 然后返回了TLE 然后google了一下题解:发现这题卡了n^2建图,需要优化建边 我这里是通过分治优化的 就是类似与建立一个虚点 一个x要向y的一个前缀建图,所以就可以类似前缀和优化建图那样, 按权值排序然后建出一条链,链上两个点之间的流量为INF,费用为权值之差,然后每个点向对应的点连边 但这样建图是错误的,原因在于我们把点排了序,改变了编号顺序, 所以一个点能到达的点不一定是它可以到达的 所以我们要固定在固定编号顺序的情况下这样连边,也就是说x的一个区间和y的一个区间之间这样连边, 要求两个区间不重合,且x的区间比y的区间小 那么很容易想到分治建图,每次让[l,mid]向[mid+1,r]连边,剩下的递归下去就行了 1 #include <set> 2 #include <map> 3 #include <stack> 4 #include <queue> 5 #include <cmath> 6

【2019.9.17】Za

本小妞迷上赌 提交于 2019-11-29 22:15:56
Za yyb Fibonacci的性质 \(gcd(f[i],f[i+1])=1\) 证明 \(gcd(f[i],f[i+1])\) \(=gcd(f[i+1]-f[i],f[i])\) \(=gcd(f[i-1],f[i])\) \(=....\) \(=gcd(f[1],f[2])=1)\) \(f[m+n]=f[m−1]f[n]+f[m]f[n+1]f[m+n]=f[m−1]f[n]+f[m]f[n+1]\) \(gcd(f[n+m],f[n])=gcd(f[n],f[m])gcd(f[n+m],f[n])=gcd(f[n],f[m])\) 由上面式子得到 \(gcd(f[n+m]=f[m−1]f[n]+f[m]f[n+1],f[n])gcd(f[n+m]=f[m−1]f[n]+f[m]f[n+1],f[n])\) \(=gcd(f[n+1]f[m],f[n])=gcd(f[n+1]f[m],f[n])\) \(=gcd(f[n+1],f[n])∗gcd(f[m],f[n])=gcd(f[n+1],f[n])∗gcd(f[m],f[n])\) \(=1∗gcd(f[m],f[n])=1∗gcd(f[m],f[n])\) \(=gcd(f[m],f[n])\) \(gcd(f[n],f[n+m])=f[gcd(n,n+m)]gcd(f[n],f[n+m])=f[gcd(n,n

[POI2012]FES-Festival [最短路 负环]

守給你的承諾、 提交于 2019-11-29 21:30:48
P3530 [POI2012]FES-Festival 略 ==只是spfa跑的时候要用递归(?)版的 普通的判负环要超时啊啊啊啊啊啊啊 #include<bits/stdc++.h> using namespace std; #define Max(x,y) ((x)>(y)?(x):(y)) #define Min(x,y) ((x)<(y)?(x):(y)) const int N=600+10,M=100000+10,inf=0x3f3f3f3f; int n,m1,m2,mp[N][N],ans=0; template <class t>void rd(t &x){ x=0;int w=0;char ch=0; while(!isdigit(ch)) w|=ch=='-',ch=getchar(); while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar(); x=w?-x:x; } int head[N],tot=0; struct edge{int v,w,nxt;}e[M<<1]; void add(int u,int v,int w){ e[++tot]=(edge){v,w,head[u]},head[u]=tot; } int idx=0,Bcnt=0,dfn[N],low[N],bl[N],sz[N];

UOJ #584. 天天去哪吃

混江龙づ霸主 提交于 2019-11-29 20:05:32
【题目描述】: 吃饭是自古以来令人头疼的问题,最后天天决定写一个程序来替他做决定。 现在已知有n个餐厅,编号从0到n-1。记ai表示第i天决定吃什么,令 t[i][0]=(A×a[i-1]+B×a[i-2])%n,(其实就是一个随机数) t[i][j]=(t[i][j-1]+1)%n,j≥1 天天不想去最近吃过的餐厅,所以如果在前n/2(整除)天中吃过某个餐厅,就不想再去这个餐厅。所以我们要找一个最小的k,使得t[i][k]不为前n/2(整除)天去过的餐厅。那么天天第i天就想去t[i][k]餐厅。 现在已知a1和a2,想让你输出a3…am,即接下来m-2天,天天会去哪里吃饭。 【输入描述】: 第一行两个正整数n和m。其中2≤n≤10^5,3≤m≤2×10^5; 第二行两个整数,分别为A和B。其中0≤A,B≤10^9; 第三行两个整数,为a[1]和a[2]。0≤a[1],a[2]<n,且a[1]≠a[2]; 【输出描述】: 一行m-2个整数,表示接下来m-2天里,天天去哪里吃饭。 【样例输入】: 3 4 7 11 2 0 【样例输出】: 1 2 【样例说明】: t[3][0]=(7×a[2]+11×a[1])%n=1,前面n/2=1天没有出现,所以第三天去1号餐厅。 t[4][0]=1,前面1天已经出现,所以第四天去t[4][1]=2号餐厅。 【时间限制、数据范围及描述】: 时间

消息扩散

余生颓废 提交于 2019-11-29 20:05:12
题目背景 本场比赛第一题,给个简单的吧,这 100 分先拿着。 题目描述 有n个城市,中间有单向道路连接,消息会沿着道路扩散,现在给出n个城市及其之间的道路,问至少需要在几个城市发布消息才能让这所有n个城市都得到消息。 输入输出格式 输入格式: 第一行两个整数n,m表示n个城市,m条单向道路。 以下m行,每行两个整数b,e表示有一条从b到e的道路,道路可以重复或存在自环。 输出格式: 一行一个整数,表示至少要在几个城市中发布消息。 输入输出样例 输入样例#1: 5 4 1 2 2 1 2 3 5 1 输出样例#1: 2 说明 【数据范围】 对于20%的数据,n≤200; 对于40%的数据,n≤2,000; 对于100%的数据,n≤100,000,m≤500,000. 【限制】 时间限制:1s,内存限制:256M 【注释】 样例中在4,5号城市中发布消息。 分析: 本题很简单???我做了好多遍。。。先%%% 牛的传说 帮我改对了这题。 本题思路就是求强连通分量,但是去重很麻烦,最后看到了题解判断入度才豁然开朗em。。。 CODE: 1 #include<iostream> 2 #include<cstdio> 3 #include<stack> 4 #include<cstring> 5 using namespace std; 6 const int M=5000005; 7

疫情控制

旧巷老猫 提交于 2019-11-29 19:37:51
洛谷 其实在很久之前我就差不多大致理解思路 但由于过于蒟蒻 难以实现 在大约一月前我刷树形dp时,又刷到这道题 嗯,我用dp get到0pts的好成绩 反正我现在就是懂了 #include<bits/stdc++.h> #define re return #define ll long long #define dec(i,l,r) for(register int i=l;i>=r;--i) #define inc(i,l,r) for(register int i=l;i<=r;++i) using namespace std; template<typename T>inline void rd(T&x) { char c;bool f=0; while((c=getchar())<'0'||c>'9')if(c=='-')f=1; x=c^48; while((c=getchar())>='0'&&c<='9')x=x*10+(c^48); if(f)x=-x; } const int maxn=300005; int cnt,k,n,m,hd[maxn],fa[maxn][21]; int size1,pos[maxn],vis[maxn]; long long dis[maxn][21]; struct node{ int to,nt,val; }e[maxn<<1];

luogu 4380 [USACO18OPEN]Multiplayer Moo

北城余情 提交于 2019-11-29 19:30:58
题目 注:题目来源 luogu4380 分析 Part 1 写在前面 看到题解里好多大佬用STL,蒟蒻瑟瑟发抖,打了两遍BFS, 过了。 这道题本身是刷并查集时刷到的,然而发现自己用并查集想不到第二问该怎么做…… (不过luogu题解里有大佬是用的并查集) 果断放弃了并查集的思路重新思考后,发现这道题到是用BFS染色可以做。 Part 2 BFS ? 第一问倒是好想,标记连通块,统计连通块的大小,最后输出最大值就好。 void bfs1(int sx,int sy){ ++tot;//连通块的编号 color[tot] = a[sx][sy];//记下连通块的颜色 queue<Node>q; q.push((Node){sx,sy}); vis[sx][sy] = tot;//标记起点 while(!q.empty()){ Node u = q.front(); q.pop(); cnt[tot]++;//记连通块的数量 for(int i = 0;i < 4; ++ i){ int nx = u.x + dx[i]; int ny = u.y + dy[i]; if(nx <= 0 || ny <= 0 || nx > n || ny > n) continue; if(!vis[nx][ny] && a[nx][ny] == a[sx][sy]){ q.push((Node)

CJOI 2005 新年好

心不动则不痛 提交于 2019-11-29 19:21:47
简要分析: 本题要求经过一定的点的最短路 类似题目: 孤岛营救问题 易得,从 i 点出发,经过 k 点 ,到达 j 点的最短路, 一定是从 i 到 k 的最短路加上从 k 到 j 的最短路 证明 :假设:从 i 点出发,经过 k 点 ,到达 j 点的最短路,不是从 i 到 k 的最短路加上从 k 到 j 的最短路 则应存在 路径 E1(i->k)+E2(k->j)<E1min+E2min 易证得 假设不成立 枚举 从每个亲戚家出发到达其它车站所需时间 再枚举每种路径所需时间 时间复杂度(5*M log M+5^5) 可以接受 注意事项 本题是无向图,注意建图和建边 注意每次dijkstra都要重新预处理 具体代码 #include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<vector> #include<queue> using namespace std; const int inf=2147483637,Max_N=50010,Max_M=100010; typedef pair<int,int>node; struct Edge { int dis,to,next; } E[Max_M*2];//注意是无向边 int Head[Max_N],Dis[6][Max_N]

NOIp2014 寻找道路

喜欢而已 提交于 2019-11-29 17:44:10
这道题本身真的不怎么难,但是 "路径上所有的点的出边所指向的点都直接或间接与终点连通" 这句话真的是太ex了。。 我隐隐约约记得当年做这道题时的懵逼,看来当时的代码确实是没什么问题,只是因为理解上的误差 教训:好好看题,看明白了再做,要不然一切都是白干。 题干 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<queue> 5 #include<algorithm> 6 7 using namespace std; 8 9 typedef long long ll; 10 11 const int Maxn = 1e4+10,Maxm = 2e5+10; 12 13 ll read(){ 14 ll ans = 0; 15 char last = ' ',ch = getchar(); 16 while(ch < '0'||ch > '9')last = ch,ch = getchar(); 17 while('0' <= ch&&ch <= '9')ans = ans*10+ch-'0',ch = getchar(); 18 if(last == '-')return -ans;return ans; 19 } 20 21 struct Edge{ 22 int to,ne; 23

【PAT甲级】1034 Head of a Gang (30 分)

送分小仙女□ 提交于 2019-11-29 15:21:42
题意: 输入两个正整数N和K(<=1000),接下来输入N行数据,每行包括两个人由三个大写字母组成的ID,以及两人通话的时间。输出团伙的个数(相互间通过电话的人数>=3),以及按照字典序输出团伙老大的ID和团伙的人数(团伙中通话时长最长的人视为老大,数据保证一个团伙仅有一名老大)。 代码: #define HAVE_STRUCT_TIMESPEC #include<bits/stdc++.h> using namespace std; string s,s2; int x[1007],y[1007]; vector<pair<int,int> >edge[20007]; bool vis[20007]; int val[20007]; int mx=0; int pos=0; int ans[20007]; int num[20007]; int cnt=0; int c[1007]; bool visedge[1007]; int sum2=0; void dfs(int x){ if(!vis[x]) ++cnt; vis[x]=1; for(auto it:edge[x]){ if(visedge[it.second]) continue; visedge[it.second]=1; if(!vis[it.first]){ ++cnt; vis[it.first]=1; }