图论

图论3 1011

本秂侑毒 提交于 2019-12-01 04:59:52
三角形 有一个等边三角形,在每条边上等距离画n个点,(顶点上不画,把每条边分成n+1段),在这3n个点中选取3个点作为新三角形的顶点,求所有不同三角形的面积和。 3n个点有各自的编号,两个三角形不同当且仅当选取编号集合不同,规定单位面积为边长每一段长度的等边三角形面积。 答案对1e9+7取模 1<=n<=1e9 题解 很容易分出两类:有两个点在同一边上,三点都在不同边。 1.记有两个点的边为底边。可以得到 $2*3\sum_{x=1}^{n-1}x(n-x)*\sum_{h=1}^{n}h$(顶点可以在两边选取,底边有三种 $3n(n+1)(n\sum_{x=1}^{n-1}x-\sum_{x=1}^{n-1}x^{2})$ $\frac{n^{2}(n+1)(n^{2}-1)}{2}$ 2.在三边分别选边,记a,b,c为三点到所在边的左端点的距离 $\sum_{a=1}^{n}\sum_{b=1}^{n}\sum_{c=1}^{n}(n+1)^{2}-(n+1-a)b-(n+1-b)c-(n+1-c)a$ $\sum_{a=1}^{n}\sum_{b=1}^{n}\sum_{c=1}^{n}(n+1)^{2}-(n+1)(a+b+c)+ab+ac+bc$ $(n+1)^{2}$与a,b,c无关,所以可以算得贡献为$n^{3}(n+1){2}$ 对于(a+b+c)可以考虑画出树形图

图论2 1010

♀尐吖头ヾ 提交于 2019-12-01 04:56:37
最小生成树 给你一个无向带权连通图,每条边是黑色或白色。让你求一棵恰好有need条白色边的权值和最小的生成树。题目保证有解。 对于所有数据,V,E<=100000,c为[1,1000]中的正整数。 题解 可以知道恰好选到need条白边就是最优的,考虑给所有白边加上一个值,随着值的增大,在生成树中的白边越少,所以可以二分。 取最后一次满足条件的值。 排序的时候,对于相同值的边白边优先。 #include<cstdio> #include<iostream> #include<algorithm> using namespace std; const int maxn=100005; int n,m,need; int fa[maxn],sum,cnt; struct edge{ int x,y,c,val; bool operator < (const edge a) const { if(val==a.val) return c<a.c; return val<a.val; } }e[maxn],cy[maxn]; template<class T>inline void read(T &x){ x=0;int f=0;char ch=getchar(); while(!isdigit(ch)) {f|=(ch=='-');ch=getchar();} while(isdigit

图论模板

*爱你&永不变心* 提交于 2019-12-01 02:48:19
1 /* // 图论模板 // */ 2 //----------------------------------------------------------------------------- 3 /*卡常小技巧*/ 4 #define re register 5 #define max(x,y) ((x)>(y)?(x):(y)) 6 #define min(x,y) ((x)<(y)?(x):(y)) 7 #define swap(x,y) ((x)^=(y)^=(x)^=(y)) 8 #define abs(x) ((x)<0?-(x):(x)) 9 inline + 函数(非递归) 10 static 相当于全局变量,防止爆栈,且不用重复申请空间,初值为0 11 //----------------------------------------------------------------------------- 12 /*前向星邻接表*/ 13 //单向链表 14 int tot,first[100010]; 15 struct node{int u,v,w,next;}edge[200010]; 16 inline void add(re int x,re int y,re int w){ 17 edge[++tot].u=x; 18 edge[tot]

7. 图论

北城以北 提交于 2019-12-01 02:04:50
最短路 最小生成树 树的直径与最近公共祖先 基环树 负环与差分约束 Tarjan算法与无向图连通性 Tarjan算法与有向图连通性 二分图的匹配 二分图的覆盖于独立集 网络流初步 总结与练习 来源: https://www.cnblogs.com/hebust-fengyu/p/11647255.html

图论1 1009

柔情痞子 提交于 2019-11-30 23:21:15
重量差异 有n个物品,m次操作:告诉物品a比b轻w个重量单位(不会矛盾),询问物品a比物品b轻多少重量单位(根据已有信息)。 对于所有数据,1<=N,M<=100000,1<=a,b<=N 题解 带权并查集模板题。 记录val为x父亲比x重多少,注意路径压缩的合并。 代码有注释。 不要把find(x)写成find(dx)(可能只有我会这么写) #include<cstdio> #include<iostream> #include<algorithm> using namespace std; const int maxn=100005; int n,m; int fa[maxn],val[maxn]; template<class T>inline void read(T &x){ x=0;int f=0;char ch=getchar(); while(!isdigit(ch)) {f|=(ch=='-');ch=getchar();} while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} x = f ? -x : x ; } int find(int x){ if(fa[x]==x) return x; //w[f]-w[fa[x]]=val[fa[x]] //w[fa[x]]-w[x]=val[x] //w[f

图论训练之八

左心房为你撑大大i 提交于 2019-11-30 22:54:21
http://poj.org/problem?id=3177 题目描述 给一个连通图,问最少加几条边可以得到边双连通图。 分析: 模板题 ,复习一下 tarjan双向边缩点,再找 叶子结点(即出度为1的点) 其实本题可以不用缩点,只用 维护low数组 就行, 只要low数组的值相等,就是属于同一连通块 为什么 要找叶子结点呢? 结论 :一个无向图通过加边得到边双联通图至少要(叶子结点数目+1)/2 #include<cstdio> #include<cstring> #include<algorithm> #include<vector> using namespace std; const int MAXN = 5010; vector<int>edge[MAXN]; int n, m; int low[MAXN], dfn[MAXN], tmpdfn, in[MAXN]; int min( int a, int b ){return a<b ?a:b;} void init() { int i; for( i = 1; i <= n ; i++ )edge[i].clear(); memset(in,0,sizeof(int)*(n+1)); memset(dfn,0,sizeof(dfn)); tmpdfn=0; } void tarjan( int u, int p ) {

图论训练之七

岁酱吖の 提交于 2019-11-30 20:43:28
https://nanti.jisuanke.com/t/A1108 本题又叫缺点最短路,数据卡的很好, 一N×N×N×N 恰好过不了 二 N×N×N×logN才行 如果一的话就可以再在floyed的基础上多枚举一维 这一维表示不经过该点 floyed的本质是一个 增量算法 ,最外一维枚举的是k,但这个顺序并 不影响最后的结果 如果可以处理处对于每个点 Y , 只剩Y没在floyed的转移矩阵里 , 这个矩阵的值就是不经过 y 点的 全源最短路 考虑分治 , 为什么要分治呢 因为 一算法 的不好在于每次排除一个点都要所有都 枚举一次 ,很多状态都是重复计算的, 比如总共有10个点,先排除点1,再排除点2,明显两次其他八个点都只用算一次就行了,而一算法,就会多次计算 而 分治 ,可以保证每个只算一次,要用的时候就把其他八个拼起来( 因为顺序不重要 ) 每一次把点集拆成两半, 每一次把点集拆成两半, 先用前一半的点在 Floyd 算法中滚,再递归后一半点。 然后回溯,用后一半的点在 Floyd 算法里滚,递归前一半的点。 这样每个只有一个点的状态得到的就是只有这个点没有在 Floyd 算法里滚的矩阵 如果实在 理解不到 的话,代码里有个注释打开, 4 0 1 -1 -1 -1 0 1 -1 -1 -1 0 1 1 -1 -1 0 输出是 l=1 r=4 l=3 r=4 l=4 r=4

【acwing板子大全】图论与搜索

早过忘川 提交于 2019-11-30 18:19:48
树与图的遍历 时间复杂度 O(n+m), n表示点数,m表示边数 (1) 深度优先遍历 —— 模板题 AcWing 846. 树的重心 int dfs(int u){ vis[u]=1; int son_size=1,now=0; ee(i,u){ int v=e[i].v; if(!vis[v]){ int t=dfs(v); now=max(now,t); son_size+=t; } } now=max(now,n-son_size); ans=min(ans,now); return son_size; } (2) 宽度优先遍历 —— 模板题 AcWing 847. 图中点的层次 queue<int>q; inline void spfa(){ mem(dis,0x3f); mem(vis,0); q.push(1); vis[1]=1; dis[1]=0; while(!q.empty()){ int u=q.front();q.pop(); vis[u]=0; ee(i,u){ int v=e[i].v,w=e[i].w; if(dis[v]>dis[u]+w){ dis[v]=dis[u]+w; if(!vis[v]){ vis[v]=1; q.push(v); } } } } } 拓扑排序 —— 模板题 AcWing 848. 有向图的拓扑序列 时间复杂度 O(n

【图论好题】ABC #142 Task F Pure

跟風遠走 提交于 2019-11-30 17:14:45
题目大意 给定一个 $N$ 个点 $M$ 条边的有向图 $G$,无重边、自环。找出图 $G$ 的一个 导出子图 (induced subgraph) $G'$,且 $G'$ 中的每个点的入度和出度都是 1。 数据范围 $ 1 \le N \le 1000$ $ 0 \le M \le 2000$ 分析 导出子图 $G'$ 中的每个点的入度和出度都是 1 相当于说 $G'$ 是一个环(cycle)。 若不考虑 $G'$ 是导出子图这个条件,则可通过 DFS 判断图 $G$ 中是否有环,若有,同时还可以找出一个环。 下面给出环的一个性质: 若有向图 $C$ 是一个环,则往 $C$ 中添一条边将产生一个更小的环。 读者自证不难。 因此若有向图 $G$ 中有环,则 $G$ 中的最小环必然是 $G$ 的导出子图。 于是原问题可以转化成求图 $G$ 中的最小环。 更进一步,可以先 DFS 找出一个环 $C$,设 $C$ 的点集是 $V_C$;接着在由 $V_C$ 导出的子图 $G_C$ 上找最一个最小环 $C'$,则 $C'$ 是 $G_C$ 的导出子图,从而也是 $G$ 的导出子图。 上述论证用到了一个导出子图的一个性质: 若 $B$ 是 $A$ 的导出子图,$C$ 是 $B$ 的导出子图,则 $C$ 也是 $A$ 的导出子图。 Implementation 下列代码是最暴力的实现。 int