#include
using namespace std;
const int N = 1e5 + 10;
// head 表示头结点的下标
// e[i] 表示节点i的值
// ne[i] 表示节点i的next指针是多少
// idx 存储当前已经用到了哪个点
int head, e[N], ne[N], idx;
// 初始化
void init()
{
head = -1;
idx = 0;
}
// 将x插到头结点
void add_to_head(int x)
{
e[idx] = x, ne[idx] = head, head = idx ++ ;
}
// 将x插到下标是k的点后面
void add(int k, int x)
{
e[idx] = x, ne[idx] = ne[k], ne[k] = idx ++ ;
}
// 将下标是k的点后面的点删掉
void remove(int k)
{
ne[k] = ne[ne[k]];
}
int main()
{
int m;
cin >> m;
init(); // 初始化
while (m -- )
{
int k, x;
char op;
cin >> op;
if (op == 'H')
{
cin >> x;
add_to_head(x);
}
else if (op == 'D')
{
cin >> k;
if (!k) head = ne[head];
else remove(k - 1);
}
else{
cin >> k >> x;
add(k - 1, x);
}
}
for (int i = head; i != -1; i = ne[i]) cout << e[i] << " ";
cout << endl;
return 0;
}
#include
using namespace std;
const int N = 1e5 + 10;
int idx, l[N], r[N], e[N];
//在节点a的右边插入x
void insert(int a, int x)
{
e[idx] = x;
l[idx] = a, r[idx] = r[a];
l[r[a]] = idx, r[a] = idx ++ ;
}
//删除节点a
void remove(int a)
{
r[l[a]] = r[a];
l[r[a]] = l[a];
}
int main()
{
//0是左端点,1是右端点
l[1] = 0, r[0] = 1, idx = 2;
int m;
cin >> m;
while (m -- )
{
string op;
int k, x;
cin >> op;
if (op == "L")
{
cin >> x;
insert(0, x);
}
else if (op == "R")
{
cin >> x;
insert(l[1], x);
}
else if (op == "D")
{
cin >> k;
remove(k + 1);
}
else if (op == "IL")
{
cin >> k >> x;
insert(l[k + 1], x);
}
else
{
cin >> k >> x;
insert(k + 1, x);
}
}
for (int i = r[0]; i != 1; i = r[i]) cout << e[i] << " ";
return 0;
}
#include
#include // memset
#include
using namespace std;
const int N = 1e5 + 10, M = 2 * N;
int n, m;
// head, e[M],ne[M],idx; 是一条单链表
// h[N], e[M],ne[M],idx; 是N条单链表
int h[N], e[M], ne[M], idx;
bool st[N]; // 用st数组存一下哪些点已经被遍历过了
int ans = N; //记录一个全局最大值
// 在a对应的单链表中插入一个节点b
void add(int a, int b)
{
e[idx] = b; // 表示第idx条边指向b点
ne[idx] = h[a]; // ne[idx]表示第idx条边的下一条边是 a点的邻接链表的第一条边
h[a] = idx++; // head[a]表示将a点的邻接链表的第一条边更新为第idx条边
}
// u表示当前已经dfs到的这个点
// 以u为根的子树中, 点的数量
int dfs(int u)
{
st[u] = true; // 标记一下, 当前这个点已经被搜索过
int sum = 1; // 记录当前子树大小
int res = 0; // 把u这个点删除之后, 每一个联通块的最大值
for (int i = h[u]; i != -1; i = ne[i]) {
int j = e[i]; // 当前这个链表中的节点, 对应图中的点的编号是多少
if (!st[j]) {
int s = dfs(j); // j这棵子树的大小
res = max(res, s); //最大的联通块大小
sum += s;
}
}
res = max(res, n - sum);
ans = min(ans, res);
return sum;
}
int main()
{
// 一条单链表 head初始化为-1
// n条单链表,把所有的head初始化为-1
memset(h, -1, sizeof h);
cin >> n;
for (int i = 0; i < n - 1; i++) {
int a, b;
cin >> a >> b;
add(a, b);
add(b, a);
}
// 随便挑一个点, 比方说从第一个点开始搜
dfs(1);
cout << ans << endl;
return 0;
}
#include
#include
#include
using namespace std;
const int N = 1e5 + 10;
int n, m;
int h[N], e[N], ne[N], idx;
int dist[N];
void add(int a, int b)
{
e[idx] = b;
ne[idx] = h[a];
h[a] = idx ++ ;
}
int bfs()
{
memset(dist, -1, sizeof dist);
queue<int> q;
q.push(1);
dist[1] = 0;
while (q.size())
{
auto t = q.front();
q.pop();
for (int i = h[t]; i != -1; i = ne[i])
{
int j = e[i];
if (dist[j] == -1)
{
dist[j] = dist[t] + 1;
q.push(j);
}
}
}
return dist[n];
}
int main()
{
memset(h, -1, sizeof h);
scanf("%d%d", &n, &m);
for (int i = 0; i < m; i ++ )
{
int a, b;
scanf("%d%d", &a, &b);
add(a, b);
}
printf("%d\n", bfs());
}
#include
#include
#include
using namespace std;
const int N = 1e5 + 10;
int h[N], e[N], ne[N], idx;
int top[N];
int d[N];
int cnt = 0;
int n, m;
void add(int a, int b)
{
e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
}
bool topsort()
{
queue<int> q;
for (int i = 1; i <= n; i ++ )
if (!d[i])
q.push(i);
while (q.size())
{
auto t = q.front();
q.pop();
top[cnt ++ ] = t;
for (int i = h[t]; i != -1; i = ne[i])
{
int j = e[i];
d[j] -- ;
if (!d[j])
q.push(j);
}
}
return cnt == n;
}
int main()
{
cin >> n >> m;
memset(h, -1, sizeof h);
for (int i = 0; i < m; i ++ )
{
int a, b;
cin >> a >> b;
add(a, b);
d[b] ++ ;
}
if (!topsort()) puts("-1");
else
{
for (int i = 0; i < n; i ++ )
{
cout << top[i];
if (i != n - 1) cout << ' ';
}
}
return 0;
}
#include
#include
using namespace std;
const int N = 1e5 + 10;
int h[N], e[N], ne[N], idx;
int q[N];
int d[N];
int n, m;
void add(int a, int b)
{
e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
}
bool topsort()
{
int hh = 0, tt = -1;
for (int i = 1; i <= n; i ++ )
if (!d[i])
q[ ++ tt] = i;
while (hh <= tt)
{
auto t = q[hh ++ ];
for (int i = h[t]; i != -1; i = ne[i])
{
int j = e[i];
d[j] -- ;
if (!d[j])
q[ ++ tt] = j;
}
}
return tt + 1 == n;
}
int main()
{
memset(h, -1, sizeof h);
cin >> n >> m;
for (int i = 0; i < m; i ++ )
{
int a, b;
cin >> a >> b;
add(a, b);
d[b] ++ ;
}
if (!topsort()) puts("-1");
else
{
for (int i = 0; i < n; i ++ )
{
cout << q[i];
if (i != n - 1) cout << ' ';
}
}
return 0;
}
#include
#include
using namespace std;
const int N = 510;
int g[N][N];
int dist[N];
bool st[N];
int n, m;
int dijkstra()
{
memset(dist, 0x3f, sizeof dist);
dist[1] = 0;
for (int i = 0; i < n - 1; i ++ )
{
int t = -1;
for (int j = 1; j <= n; j ++ )
if (!st[j] && (t == -1 || dist[t] > dist[j]))
t = j;
for (int j = 1; j <= n; j ++ )
dist[j] = min(dist[j], dist[t] + g[t][j]);
st[t] = true;
}
if (dist[n] == 0x3f3f3f3f) return -1;
return dist[n];
}
int main()
{
memset(g, 0x3f, sizeof g);
cin >> n >> m;
for (int i = 0; i < m; i ++ )
{
int a, b, c;
cin >> a >> b >> c;
g[a][b] = min(g[a][b], c);
}
printf("%d", dijkstra());
return 0;
}
#include
#include
#include
#include
using namespace std;
const int N = 1e6 + 10;
typedef pair<int, int> pii;
int n, m;
int head[N], e[N], ne[N], idx, w[N];
int dist[N]; //从1号点走到每个点, 当前的最短距离是多少
bool st[N]; //用于在更新最短距离时,判断当前的点的最短距离是否确定,是否需要更新
void add(int a, int b, int c)
{
e[idx] = b;
w[idx] = c;
ne[idx] = head[a];
head[a] = idx++;
}
// 进行n次迭代后最后就可以确定每个点的最短距离
// 然后再根据题意输出相应的 要求的最短距离
int dijkstra()
{
memset(dist, 0x3f, sizeof dist);
dist[1] = 0; // 第一个点到自己的距离为0
priority_queue<pii, vector<pii>, greater<pii>> heap; //转换为小根堆
heap.push({0, 1}); //将1号点放进来, 值是0, 编号是1
while (heap.size()) {
auto t = heap.top(); //每次找到堆中最小的点
heap.pop();
int ver = t.second, distance = t.first; //距离最小的点的编号和距离
if (st[ver]) { //如果这个点被访问过, 就continue
continue;
}
st[ver] = true;
// 更新当前这个点的所有出边
for (int i = head[ver]; i != -1; i = ne[i]) {
int j = e[i];
if (dist[j] > distance + w[i]) {
dist[j] = distance + w[i];
heap.push({dist[j], j});
}
}
}
if (dist[n] == 0x3f3f3f3f) { // 如果第n个点路径为无穷大即不存在最低路径
return -1;
}
return dist[n];
}
int main()
{
cin >> n >> m;
memset(head, -1, sizeof head);
for (int i = 0; i < m; i++) {
int a, b, c;
cin >> a >> b >> c;
add(a, b, c); //用邻接表存, 重边就无所谓了
}
// 求单源最短路径
cout << dijkstra() << endl;
return 0;
}
#include
#include
#include
using namespace std;
const int N = 510, M = 10010;
struct Edge
{
int a, b, c;
} edges[M];
int n, m, k;
int dist[N];
int last[N];
void bellman_ford()
{
memset(dist, 0x3f, sizeof dist);
dist[1] = 0;
for (int i = 0; i < k; i++) {
memcpy(last, dist, sizeof dist); //只用上一次迭代的结果
for (int j = 0; j < m; j++) {
auto e = edges[j];
dist[e.b] = min(dist[e.b], last[e.a] + e.c);
}
}
}
int main()
{
cin >> n >> m >> k;
for (int i = 0; i < m; i++) {
int a, b, c;
cin >> a >> b >> c;
edges[i] = {a, b, c};
}
bellman_ford();
if (dist[n] > 0x3f3f3f3f / 2) {
cout << "impossible" << endl;
}
else {
cout << dist[n] << endl;
}
return 0;
}
#include
#include
#include
using namespace std;
const int N = 1e5 + 10;
int n, m;
int head[N], e[N], ne[N], w[N], idx;
bool st[N];
int dist[N];
void add(int a, int b, int c)
{
e[idx] = b;
w[idx] = c;
ne[idx] = head[a];
head[a] = idx++;
}
int spfa()
{
memset(dist, 0x3f, sizeof dist);
dist[1] = 0;
queue<int> q;
q.push(1);
st[1] = true; //判重数组, 队列中有重复的点没有意义
while (q.size()) {
int t = q.front();
q.pop();
st[t] = false;
for (int i = head[t]; i != -1; i = ne[i]) {
int j = e[i];
if (dist[j] > dist[t] + w[i]) {
dist[j] = dist[t] + w[i];
if (!st[j]) {
q.push(j);
st[j] = true;
}
}
}
}
if (dist[n] == 0x3f3f3f3f) {
return -1;
}
return dist[n];
}
int main()
{
cin >> n >> m;
memset(head, -1, sizeof head);
for (int i = 0; i < m; i++) {
int a, b, c;
cin >> a >> b >> c;
add(a, b, c);
}
int t = spfa();
if (t == -1) {
cout << "impossible" << endl;
}
else {
cout << dist[n] << endl;
}
return 0;
}
#include
#include
#include
using namespace std;
const int N = 2e3 + 10, M = 1e4 + 10;
int n, m;
int head[N], e[M], ne[M], w[M], idx;
bool st[N];
int dist[N]; // 表示 当前从1 -> x的最短距离
int cnt[N]; //cnt[x] 表示 当前从1 -> x的最短路的边数
void add(int a, int b, int c)
{
e[idx] = b;
ne[idx] = head[a];
w[idx] = c;
head[a] = idx++;
}
bool spfa(){
// 这里不需要初始化dist数组为 正无穷/初始化的原因是, 如果存在负环, 那么dist不管初始化为多少, 都会被更新
queue<int> q;
//不仅仅是1了, 因为点1可能到不了有负环的点, 因此把所有点都加入队列
for(int i=1;i<=n;i++){
q.push(i);
st[i]=true;
}
while(q.size()){
int t = q.front();
q.pop();
st[t]=false;
for(int i = head[t];i!=-1; i=ne[i]){
int j = e[i];
if(dist[j]>dist[t]+w[i]){
dist[j] = dist[t]+w[i];
cnt[j] = cnt[t]+1;
if(cnt[j]>=n){ // 有n条边,则n + 1个点,抽屉原理,有两个点是同一个点,则说明路径上存在环,又因为路径变小,说明存在负环
return true;
}
if(!st[j]){
q.push(j);
st[j]=true;
}
}
}
}
return false;
}
int main()
{
cin >> n >> m;
memset(head, -1, sizeof head);
for (int i = 0; i < m; i++) {
int a, b, c;
cin >> a >> b >> c;
add(a, b, c);
}
if (spfa()) {
cout << "Yes" << endl;
}
else {
cout << "No" << endl;
}
return 0;
}
#include
#include
#include
using namespace std;
const int N = 210, INF = 1e9;
int n, m, Q;
int d[N][N];
void floyd()
{
for (int k = 1; k <= n; k++) {
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
}
}
}
}
int main()
{
cin >> n >> m >> Q;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
if (i == j) {
d[i][j] = 0;
}
else {
d[i][j] = INF;
}
}
}
while (m--) {
int a, b, c;
cin >> a >> b >> c;
d[a][b] = min(d[a][b], c);
}
floyd();
while (Q--) {
int a, b;
cin >> a >> b;
int t = d[a][b];
if (t > INF / 2) {
cout << "impossible" << endl;
}
else {
cout << t << endl;
}
}
return 0;
}
#include
#include
using namespace std;
const int N = 510;
const int INF = 0x3f3f3f3f;
int g[N][N];
int dist[N];
bool st[N];
int n, m;
int prim()
{
memset(dist, 0x3f, sizeof dist);
int res = 0;
dist[1] = 0;
for (int i = 0; i < n; i ++ )
{
int t = -1;
for (int j = 1; j <= n; j ++ )
if (!st[j] && (t == -1 || dist[t] > dist[j]))
t = j;
if (i && dist[t] == INF) // 如果i为0不用
return INF;
st[t] = true; // 标记
if (i) res += dist[t]; // 如果i为0不用累加
for (int j = 1; j <= n; j ++ )
dist[j] = min(dist[j], g[t][j]); // 是与g做比较,因为t已经是最小生成树里的了
}
// 返回累加答案
return res;
}
int main()
{
cin >> n >> m;
memset(g, 0x3f, sizeof g);
while (m -- )
{
int u, v, w;
cin >> u >> v >> w;
g[u][v] = g[v][u] = min(g[u][v], w);
}
int t = prim();
if (t == INF) puts("impossible");
else cout << t << endl;
return 0;
}
#include
#include
using namespace std;
const int N = 1e5 + 10, M = 2e5 + 10, INF = 0x3f3f3f3f;
int n, m;
int fa[N];
struct Edge
{
int a, b, w;
bool operator< (const Edge &W) const
{
return w < W.w;
}
}edges[M];
int find(int x)
{
if (fa[x] != x) fa[x] = find(fa[x]);
return fa[x];
}
int kruskai()
{
for (int i = 1; i <= n; i ++ ) fa[i] = i; // 初始化并查集
int res = 0, cnt = 0;1
for (int i = 0; i < m; i ++ )
{
int a = edges[i].a, b = edges[i].b, w = edges[i].w;
a = find(a), b = find(b);
if (a != b)
{
res += w;
cnt ++ ;
fa[a] = b;
}
}
if (cnt < n - 1) return INF;
return res;
}
int main()
{
cin >> n >> m;
for (int i = 0; i < m; i ++ )
cin >> edges[i].a >> edges[i].b >> edges[i].w;
sort(edges, edges + m); // 排序
int t = kruskai();
if (t == INF)
puts("impossible");
else
cout << t;
return 0;
}
#include
#include
#include
using namespace std;
const int N = 1e5 + 10, M = 2 * N; // 无向图,边存两次,数组两倍
int h[N], e[M], ne[M], idx;
int co[N];
int n, m;
void add(int a, int b)
{
e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
}
bool dfs(int u, int c)
{
co[u] = c;
for (int i = h[u]; i != -1; i = ne[i])
{
int j = e[i];
if (!co[j] && !dfs(j, 3 - c))
return false;
else if (co[j] == c)
return false;
}
return true;
}
int main()
{
memset(h, -1, sizeof h);
cin >> n >> m;
for (int i = 0; i < m; i ++ )
{
int u, v;
cin >> u >> v;
add(u, v);
add(v, u); // 无向图
}
bool success = true;
for (int i = 1; i <= n; i ++ ) // 图可能不连通
if (!co[i] && !dfs(i, 1))
{
success = false;
break;
}
if (success) puts("Yes");
else puts("No");
return 0;
}
#include
#include
using namespace std;
const int N = 510, M = 1e5 + 10;
int h[N], e[M], ne[M], idx;
bool st[N]; // st数组代表对于当前左部节点,右部的这个节点在它这轮的匹配中是否被“询问”过;在同一轮中不要重复询问同一个点
int match[N];
int n1, n2, m;
void add(int a, int b)
{
e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
}
bool find(int x)
{
for (int i = h[x]; i != -1; i = ne[i])
{
int j = e[i];
if (!st[j])
{
st[j] = true;
if (match[j] == 0 || find(match[j]))
{
match[j] = x;
return true;
}
}
}
return false;
}
int main()
{
memset(h, -1, sizeof h);
cin >> n1 >> n2 >> m;
for (int i = 0; i < m; i ++ )
{
int a, b;
cin >> a >> b;
add(a, b);
// add(b, a); 从左部匹配右部,所以即使无向图,加了会wa
}
int res = 0;
for (int i = 1; i <= n1; i ++ )
{
memset(st, 0, sizeof st);
if (find(i)) res ++ ;
}
cout << res << endl;
return 0;
}