Two Graphs

链接:https://www.nowcoder.com/acm/contest/139/D
 

题目描述

Two undirected simple graphs and where are isomorphic when there exists a bijection on V satisfying  if and only if {x, y} ∈ E2.
Given two graphs and , count the number of graphs satisfying the following condition:
* .
* G1 and G are isomorphic.

输入描述:

The input consists of several test cases and is terminated by end-of-file.
The first line of each test case contains three integers n, m1 and m2 where |E1| = m1 and |E2| = m2.
The i-th of the following m1 lines contains 2 integers ai and bi which denote {ai, bi} ∈ E1.
The i-th of the last m2 lines contains 2 integers ai and bi which denote {ai, bi} ∈ E2.

输出描述:

For each test case, print an integer which denotes the result.

示例1

输入

复制

3 1 2
1 3
1 2
2 3
4 2 3
1 2
1 3
4 1
4 2
4 3

输出

复制

2
3

备注:

* 1 ≤ n ≤ 8
* 
* 1 ≤ ai, bi ≤ n
* The number of test cases does not exceed 50.

题意:

就是在E2中选择某些边构成G1的同构,问几种方法

分析:

暴力深搜

代码:

#include<bits/stdc++.h>
using namespace std;

int n,m1,m2,a,b;
int look[10][10],vis[10][10],pre[10],w[10],ans;
map<long long,int>mm;

struct AA
{
    int x,y;
}pos[50];

int dfs(int rt,long long pp)
{
    if(rt==n+1)
    {
        long long pp=0;
        for(int i=1;i<=m1;i++)
        {
            if(vis[pre[pos[i].x]][pre[pos[i].y]]==0) return 0;
            pp|=1<<vis[pre[pos[i].x]][pre[pos[i].y]];
        }
        if(mm[pp]) return 0;//判断选择的E2的边是否重复
        ans++;
        mm[pp]=1;
        return 0;
    }
    for(int i=1;i<=n;i++)
    {
        if(w[i]) continue;
        pre[rt]=i;//映射E1中的rt代表E2中的i
        w[i]=1;
        dfs(rt+1,pp*10+i);
        w[i]=0;
    }
    return 0;
}
int main()
{
    while(~scanf("%d%d%d",&n,&m1,&m2))
    {
        mm.clear();
        memset(look,0,sizeof(look));
        memset(vis,0,sizeof(vis));
        memset(w,0,sizeof(w));
        ans=0;
        for(int i=1;i<=n;i++)
        {
            pre[i]=i;
        }
        int x,y;
        for(int i=1;i<=m1;i++)
        {
            scanf("%d%d",&x,&y);
            look[x][y]=look[y][x]=1;
            pos[i].x=x;
            pos[i].y=y;
        }
        for(int i=1;i<=m2;i++)
        {
            scanf("%d%d",&x,&y);
            vis[x][y]=vis[y][x]=i;
        }
        dfs(1,0);
        printf("%d\n",ans);
    }
    return 0;
}

 

import cv2 import numpy as np import time import collections # --- 模拟参数 (部分保留用于绘图和逻辑) --- # WIDTH, HEIGHT 将从视频帧中获取 # CENTER_X, CENTER_Y, ROI_INNER_RADIUS, ROI_OUTER_RADIUS 需要根据实际视频画面调整 SIMULATED_LAMBDA = 0.632 # 模拟激光波长 (例如 HeNe 激光的 0.632 um) MIRROR_MOVEMENT_PER_FRINGE = SIMULATED_LAMBDA / 2.0 # 每经过一个条纹,反射镜移动 lambda/2 # --- 光流法参数 (保持不变) --- fb_params = dict( pyr_scale=0.5, levels=3, winsize=15, iterations=3, poly_n=5, poly_sigma=1.2, flags=0 ) # --- 绘图参数 (保持不变) --- MAX_GRAPH_POINTS = 200 GRAPH_HEIGHT = 150 GRAPH_WIDTH = 0 # 暂时设为0,将在获取第一帧后更新 time_points = collections.deque(maxlen=MAX_GRAPH_POINTS) displacement_points = collections.deque(maxlen=MAX_GRAPH_POINTS) velocity_points = collections.deque(maxlen=MAX_GRAPH_POINTS) # --- UI 显示参数 (调整高度以适应新的布局) --- INFO_DISPLAY_HEIGHT = 120 # 增加信息显示区域高度 TOTAL_CANVAS_HEIGHT = 0 # 暂时设为0,将在获取第一帧后更新 display_canvas = None # 暂时设为None # --- 圆环检测参数 (新增) --- # 这些参数对霍夫圆变换非常重要,需要根据实际视频调整! HOUGH_DP = 1 HOUGH_MIN_DIST = 20 HOUGH_PARAM1 = 100 HOUGH_PARAM2 = 30 HOUGH_MIN_RADIUS = 10 HOUGH_MAX_RADIUS = 150 # --- 函数定义 --- # detect_and_estimate_center 函数将不再在主循环中被调用,但保留其定义 # 如果未来需要切换回动态检测,可以取消注释相关代码行 def detect_and_estimate_center(image_gray, hough_params): """ 使用霍夫圆变换检测圆环,并估计同心圆的中心。 返回 (cx, cy) 或 None。 """ # 对图像进行高斯模糊以减少噪声,这有助于霍夫变换 blurred_image = cv2.GaussianBlur(image_gray, (9, 9), 2) circles = cv2.HoughCircles(blurred_image, cv2.HOUGH_GRADIENT, hough_params['dp'], hough_params['min_dist'], param1=hough_params['param1'], param2=hough_params['param2'], minRadius=hough_params['min_radius'], maxRadius=hough_params['max_radius']) if circles is not None: circles = np.uint16(np.around(circles)) # 提取所有检测到的圆心 center_x_coords = circles[0, :, 0] center_y_coords = circles[0, :, 1] # 简单地取所有圆心的平均值作为估计的干涉中心 estimated_cx = int(np.mean(center_x_coords)) estimated_cy = int(np.mean(center_y_coords)) return (estimated_cx, estimated_cy) return None def analyze_flow_direction(flow, center_x, center_y, inner_r, outer_r): """分析光流的径向运动方向 (与原代码相同)""" h, w = flow.shape[:2] radial_flow_sum = 0 flow_count = 0 mask = np.zeros((h, w), dtype=np.uint8) # 创建掩码选择ROI cv2.circle(mask, (center_x, center_y), outer_r, 255, -1) cv2.circle(mask, (center_x, center_y), inner_r, 0, -1) # 在ROI内采样分析光流 (优化性能,不必逐像素) for r_idx in range(inner_r, outer_r, 5): # 每隔5个像素半径采样 for angle_deg in range(0, 360, 15): # 每隔15度采样 angle_rad = np.deg2rad(angle_deg) x = int(center_x + r_idx * np.cos(angle_rad)) y = int(center_y + r_idx * np.sin(angle_rad)) if 0 <= x < w and 0 <= y < h and mask[y, x] > 0: # 确保在图像和ROI内 fx, fy = flow[y, x] if abs(fx) < 0.1 and abs(fy) < 0.1: # 忽略非常小的光流 continue rad_vx = x - center_x rad_vy = y - center_y dot_product = fx * rad_vx + fy * rad_vy radial_flow_sum += np.sign(dot_product) # 只关心方向的累计效应 flow_count += 1 if flow_count > 10: # 需要足够多的有效光流点 return radial_flow_sum / flow_count return 0 def draw_graph(canvas, x_data_deque, y_data_deque, color, title, y_min, y_max, graph_x_origin, graph_y_origin, graph_w, graph_h): """在指定的canvas区域绘制线图 (与原代码相同)""" # 绘制图表背景和标题 cv2.rectangle(canvas, (graph_x_origin, graph_y_origin), (graph_x_origin + graph_w, graph_y_origin + graph_h), (40, 40, 40), -1) cv2.putText(canvas, title, (graph_x_origin + 10, graph_y_origin + 20), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (220, 220, 220), 1) if not y_data_deque or len(y_data_deque) < 2: return # Y轴范围和零位线 (如果y_min和y_max跨越0) y_range = y_max - y_min if abs(y_range) < 1e-6: y_range = 1.0 # 避免除以零 if y_min < 0 < y_max: zero_line_y = graph_y_origin + graph_h - int((-y_min / y_range) * graph_h) cv2.line(canvas, (graph_x_origin, zero_line_y), (graph_x_origin + graph_w - 10, zero_line_y), (100, 100, 100), 1) # 准备数据点进行绘制 points = [] num_plot_points = len(y_data_deque) for i in range(num_plot_points): # X 坐标:基于数据点在deque中的相对位置,映射到图表宽度 px = graph_x_origin + int((i / (MAX_GRAPH_POINTS - 1 if MAX_GRAPH_POINTS > 1 else 1)) * (graph_w - 10)) # 留出右边距 # Y 坐标:将y值按y_min, y_max缩放到图表高度 py_scaled_val = (y_data_deque[i] - y_min) / y_range py = graph_y_origin + graph_h - int(py_scaled_val * graph_h) # OpenCV的Y轴是向下的 py = np.clip(py, graph_y_origin, graph_y_origin + graph_h) # 确保在图表区域内 points.append((px, py)) if len(points) >= 2: cv2.polylines(canvas, [np.array(points, dtype=np.int32)], False, color, 1) # 绘制Y轴刻度标签 cv2.putText(canvas, f"{y_max:.2f}", (graph_x_origin + graph_w - 45, graph_y_origin + 15), cv2.FONT_HERSHEY_SIMPLEX, 0.4, (180, 180, 180), 1) cv2.putText(canvas, f"{y_min:.2f}", (graph_x_origin + graph_w - 45, graph_y_origin + graph_h - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.4, (180, 180, 180), 1) # --- 主循环 --- # *** 将 "your_video_file.mp4" 替换为你的视频文件实际路径 *** video_path = "E:\\python files\\参数试调整.mp4" cap = cv2.VideoCapture(video_path) if not cap.isOpened(): print(f"错误:无法打开视频文件 '{video_path}'。请检查文件路径和文件是否存在。") exit() # 获取视频分辨率,并设置显示画布大小 ret, frame = cap.read() if not ret: print(f"错误:无法从视频文件 '{video_path}' 获取第一帧。") exit() if len(frame.shape) == 3: VIDEO_HEIGHT, VIDEO_WIDTH, _ = frame.shape else: VIDEO_HEIGHT, VIDEO_WIDTH = frame.shape # --- MODIFICATION START --- # Define fixed center coordinates. THESE ARE NOW CONSTANT. # Set these values according to where the center of your fringes is in the video. # If you want to use the (400,387) from your original code: FIXED_CENTER_X, FIXED_CENTER_Y = (400, 387) # CURRENT_CENTER_X and CURRENT_CENTER_Y will now simply reference these fixed values CURRENT_CENTER_X = FIXED_CENTER_X CURRENT_CENTER_Y = FIXED_CENTER_Y # --- MODIFICATION END --- # Calculate widths for left and right panes LEFT_PANE_WIDTH = VIDEO_WIDTH # Left video area width equals original video width RIGHT_PANE_WIDTH = VIDEO_WIDTH # Right plotting area width also equals video width, adjust ratio if needed TOTAL_CANVAS_WIDTH = LEFT_PANE_WIDTH + RIGHT_PANE_WIDTH # Calculate total canvas height # Main content area height is the maximum of video height and the total height of two graphs MAIN_CONTENT_HEIGHT = max(VIDEO_HEIGHT, GRAPH_HEIGHT * 2) TOTAL_CANVAS_HEIGHT = INFO_DISPLAY_HEIGHT + MAIN_CONTENT_HEIGHT # Set the actual width for graphs GRAPH_WIDTH = RIGHT_PANE_WIDTH # Initialize the main display canvas display_canvas = np.zeros((TOTAL_CANVAS_HEIGHT, TOTAL_CANVAS_WIDTH, 3), dtype=np.uint8) # BGR # 请根据你的实际干涉图像调整 ROI # ROI 半径现在是相对于固定中心 ROI_INNER_RADIUS = int(min(VIDEO_WIDTH, VIDEO_HEIGHT) * 0.10) # 内部半径,例如图像较小维度的10% ROI_OUTER_RADIUS = int(min(VIDEO_WIDTH, VIDEO_HEIGHT) * 0.27) # 外部半径,例如图像较小维度的40% prev_gray = None # 用于环数统计 accumulated_radial_displacement = 0.0 # 累计径向位移 (像素) # 径向流与环数转换因子 (需要根据实际情况标定) # 假设一个环的半径变化(涌现/消失)对应50像素的径向位移。 PIXELS_PER_FRINGE = 120 # 这是一个需要根据实际干涉图像和系统进行校准的关键参数。 rings_emerged_count = 0 rings_disappeared_count = 0 # 光流检测状态 current_motion_state_flow = "UNKNOWN" stable_direction_counter = 0 DIRECTION_CHANGE_THRESHOLD_FLOW = 0.05 STABILITY_FRAMES_FLOW = 5 frame_num = 0 start_time = time.time() # 图表Y轴动态范围的初始值 disp_min_val, disp_max_val = 0.0, 0.0 vel_min_val, vel_max_val = 0.0, 0.0 # 霍夫圆参数字典,方便传递给函数 hough_params = { 'dp': HOUGH_DP, 'min_dist': HOUGH_MIN_DIST, 'param1': HOUGH_PARAM1, 'param2': HOUGH_PARAM2, 'min_radius': HOUGH_MIN_RADIUS, 'max_radius': HOUGH_MAX_RADIUS } print(f"开始分析视频文件: '{video_path}'。按 'q' 退出。") while True: frame_num += 1 time_points.append(frame_num) ret, frame = cap.read() if not ret: print("视频播放完毕或无法读取帧。") break # 视频播放完毕 current_gray_real = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # --- MODIFICATION START --- # Removed dynamic center detection: # detected_center = detect_and_estimate_center(current_gray_real, hough_params) # if detected_center is not None: # CURRENT_CENTER_X, CURRENT_CENTER_Y = detected_center # CURRENT_CENTER_X and CURRENT_CENTER_Y remain constant as defined before the loop. # --- MODIFICATION END --- # 1. 光流计算与方向分析 avg_radial_flow = 0.0 if prev_gray is not None: blurred_prev = cv2.GaussianBlur(prev_gray, (5, 5), 0) blurred_curr = cv2.GaussianBlur(current_gray_real, (5, 5), 0) flow = cv2.calcOpticalFlowFarneback(blurred_prev, blurred_curr, None, **fb_params) # analyze_flow_direction 仍然使用 CURRENT_CENTER_X 和 CURRENT_CENTER_Y (现在是固定值) avg_radial_flow = analyze_flow_direction(flow, CURRENT_CENTER_X, CURRENT_CENTER_Y, ROI_INNER_RADIUS, ROI_OUTER_RADIUS) # 更新基于光流的运动状态 new_motion_state_candidate_flow = current_motion_state_flow if avg_radial_flow > DIRECTION_CHANGE_THRESHOLD_FLOW: detected_direction_str_flow = "OUTWARD (消失)" elif avg_radial_flow < -DIRECTION_CHANGE_THRESHOLD_FLOW: detected_direction_str_flow = "INWARD (涌现)" else: detected_direction_str_flow = "STATIONARY/UNCERTAIN" if detected_direction_str_flow == current_motion_state_flow: stable_direction_counter += 1 elif detected_direction_str_flow != "STATIONARY/UNCERTAIN": if detected_direction_str_flow == new_motion_state_candidate_flow: stable_direction_counter += 1 else: new_motion_state_candidate_flow = detected_direction_str_flow stable_direction_counter = 1 if stable_direction_counter >= STABILITY_FRAMES_FLOW: current_motion_state_flow = new_motion_state_candidate_flow else: stable_direction_counter = 0 # 2. 环数统计 (基于径向光流累积) radial_flow_scaled = avg_radial_flow * 10 # 调整这个乘数,使其更接近实际像素位移 accumulated_radial_displacement += radial_flow_scaled if accumulated_radial_displacement >= PIXELS_PER_FRINGE: rings_emerged_count += int(accumulated_radial_displacement / PIXELS_PER_FRINGE) accumulated_radial_displacement %= PIXELS_PER_FRINGE # 保留余数 elif accumulated_radial_displacement <= -PIXELS_PER_FRINGE: rings_disappeared_count += int(abs(accumulated_radial_displacement) / PIXELS_PER_FRINGE) accumulated_radial_displacement = - (abs(accumulated_radial_displacement) % PIXELS_PER_FRINGE) # 保留余数,保持负号 prev_gray = current_gray_real.copy() # 3. 计算位移和速度,用于绘图 current_mirror_velocity = avg_radial_flow velocity_points.append(current_mirror_velocity) if len(displacement_points) == 0: current_mirror_displacement = 0.0 else: current_mirror_displacement = displacement_points[-1] + current_mirror_velocity displacement_points.append(current_mirror_displacement) # 简单动态调整Y轴范围 if displacement_points: disp_min_val = min(min(displacement_points), disp_min_val, current_mirror_displacement - 0.1) disp_max_val = max(max(displacement_points), disp_max_val, current_mirror_displacement + 0.1) if velocity_points: vel_min_val = min(min(velocity_points), vel_min_val, current_mirror_velocity - 0.01) vel_max_val = max(max(velocity_points), vel_max_val, current_mirror_velocity + 0.01) # --- 4. 显示 --- display_canvas[:, :] = (20, 20, 20) # Fill canvas with dark gray # A. Information Display Area (Top) info_area_y_start = 0 # Y-coordinates for text are relative to the top of the info area cv2.putText(display_canvas, f"Flow Metric (avg_radial_flow): {avg_radial_flow:.3f}", (10, info_area_y_start + 20), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 1) cv2.putText(display_canvas, f"Emerged Rings: {rings_emerged_count}", (10, info_area_y_start + 40), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (50, 200, 255), 1) cv2.putText(display_canvas, f"Disappeared Rings: {rings_disappeared_count}", (10, info_area_y_start + 60), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (50, 200, 255), 1) cv2.putText(display_canvas, f"Accumulated Radial Disp: {accumulated_radial_displacement:.2f} px", (10, info_area_y_start + 80), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 100, 100), 1) # Now shows FIXED center, not "detected" cv2.putText(display_canvas, f"Fixed Center: ({CURRENT_CENTER_X}, {CURRENT_CENTER_Y})", (10, info_area_y_start + 100), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (100, 255, 255), 1) # Add status and FPS to the info display cv2.putText(display_canvas, f"Flow State: {current_motion_state_flow}", (TOTAL_CANVAS_WIDTH // 2 + 10, info_area_y_start + 20), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (200, 255, 50), 1) cv2.putText(display_canvas, f"FPS: {frame_num / (time.time() - start_time):.2f}", (TOTAL_CANVAS_WIDTH // 2 + 10, info_area_y_start + 40), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (200, 255, 50), 1) # B. Video Frame Display Area (Left) video_display_x_start = 0 video_display_y_start = INFO_DISPLAY_HEIGHT # Ensure video frame dimensions match the preset VIDEO_WIDTH/HEIGHT display_frame = cv2.cvtColor(current_gray_real, cv2.COLOR_GRAY2BGR) if display_frame.shape[0] != VIDEO_HEIGHT or display_frame.shape[1] != VIDEO_WIDTH: display_frame = cv2.resize(display_frame, (VIDEO_WIDTH, VIDEO_HEIGHT)) display_canvas[video_display_y_start : video_display_y_start + VIDEO_HEIGHT, video_display_x_start : video_display_x_start + VIDEO_WIDTH] = display_frame # Draw ROI circles on the live frame using the FIXED center cv2.circle(display_canvas, (CURRENT_CENTER_X + video_display_x_start, CURRENT_CENTER_Y + video_display_y_start), ROI_OUTER_RADIUS, (0, 0, 255), 2) cv2.circle(display_canvas, (CURRENT_CENTER_X + video_display_x_start, CURRENT_CENTER_Y + video_display_y_start), ROI_INNER_RADIUS, (0, 0, 255), 2) cv2.circle(display_canvas, (CURRENT_CENTER_X + video_display_x_start, CURRENT_CENTER_Y + video_display_y_start), 5, (0, 255, 255), -1) # Center point # C. Plotting Area (Right) graphs_x_start = LEFT_PANE_WIDTH # Plotting area starts to the right of the left video pane graphs_y_start = INFO_DISPLAY_HEIGHT # Plotting area aligns with the top of the video pane, below info area # Draw Displacement Graph draw_graph(display_canvas, time_points, displacement_points, (0, 255, 0), f"Detected Relative Displacement (Arbitrary Units)", disp_min_val, disp_max_val, graphs_x_start, graphs_y_start, RIGHT_PANE_WIDTH, GRAPH_HEIGHT) # Draw Velocity Graph (below the displacement graph) draw_graph(display_canvas, time_points, velocity_points, (0, 255, 255), "Detected Velocity (Flow Units/frame)", vel_min_val, vel_max_val, graphs_x_start, graphs_y_start + GRAPH_HEIGHT, RIGHT_PANE_WIDTH, GRAPH_HEIGHT) cv2.imshow('Michelson Interferometer Video Analysis', display_canvas) key = cv2.waitKey(1) & 0xFF # Adjust delay as appropriate, 1ms is near real-time if key == ord('q'): break end_time = time.time() total_time = end_time - start_time if total_time > 0: print(f"Analysis complete. Total frames: {frame_num}, Total time: {total_time:.2f}s, Average FPS: {frame_num / total_time:.2f}") else: print(f"Analysis complete. Total frames: {frame_num}, Total time: {total_time:.2f}s") cap.release() cv2.destroyAllWindows()要将上面代码处理的显示结果显示在labview上面,怎么实现
最新发布
07-16
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值